Format markdown with prettier and prepare SVG graphs for hooks (#4206)

* Use prettier to format markdown

* Add hooks graphs
pull/4208/head
Lukas Taegert-Atkinson 3 years ago committed by GitHub
parent 2f74020e2c
commit 69c099c924
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,13 +1,8 @@
---
name: 🆘 Support, Help, and Advice
about: 👉🏽 Need help or tech support? Please don't open an issue! Head to https://is.gd/rollup_chat or https://stackoverflow.com/questions/tagged/rollupjs.
---
Hey there! If you need help or tech support then this is not the place to
ask. Please head to the [Rollup Discord](https://is.gd/rollup_chat)
instead or post a question to https://stackoverflow.com/questions/tagged/rollupjs.
Hey there! If you need help or tech support then this is not the place to ask. Please head to the [Rollup Discord](https://is.gd/rollup_chat) instead or post a question to https://stackoverflow.com/questions/tagged/rollupjs.
If you arrived here because you think Rollup's documentation is unclear,
insufficient or wrong, please consider creating an issue for the documentation
instead.
If you arrived here because you think Rollup's documentation is unclear, insufficient or wrong, please consider creating an issue for the documentation instead.

@ -14,6 +14,7 @@
-->
This PR contains:
- [ ] bugfix
- [ ] feature
- [ ] refactor
@ -21,14 +22,17 @@ This PR contains:
- [ ] other
Are tests included?
- [ ] yes (*bugfixes and features will not be merged without tests*)
- [ ] yes (_bugfixes and features will not be merged without tests_)
- [ ] no
Breaking Changes?
- [ ] yes (*breaking changes will not be merged unless absolutely necessary*)
- [ ] yes (_breaking changes will not be merged unless absolutely necessary_)
- [ ] no
List any relevant issue numbers:
<!--
If this PR resolves any issues, list them as

@ -0,0 +1,2 @@
cli/help.md
LICENSE.md

@ -1,7 +0,0 @@
{
"arrowParens": "avoid",
"printWidth": 100,
"singleQuote": true,
"trailingComma": "none",
"useTabs": true
}

@ -0,0 +1,17 @@
{
"arrowParens": "avoid",
"printWidth": 100,
"singleQuote": true,
"trailingComma": "none",
"useTabs": true,
"overrides": [
{
"files": "*.md",
"options": {
"useTabs": false,
"tabWidth": 2,
"proseWrap": "never"
}
}
]
}

File diff suppressed because it is too large Load Diff

@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities

@ -4,7 +4,8 @@
First, thank you for considering contributing to rollup! It's people like you that make the open source community such a great community! 😊
We welcome any type of contribution, not only code. You can help with
We welcome any type of contribution, not only code. You can help with
- **QA**: file bug reports, the more details you can give the better (i.e. [REPL](https://rollupjs.org/repl/)-links or repos that demonstrate the specific issue)
- **Marketing**: writing blog posts, howto's, printing stickers, ...
- **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ...
@ -13,7 +14,7 @@ We welcome any type of contribution, not only code. You can help with
## Your First Contribution
Working on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
Working on your first Pull Request? You can learn how from this _free_ series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
## Submitting code
@ -27,21 +28,17 @@ It is also always helpful to have some context for your pull request. What was t
## Financial contributions
We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/rollup).
Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.
We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/rollup). Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.
## Questions
If you require technical assistance, [Stackoverflow](https://stackoverflow.com/questions/tagged/rollupjs) or [Discord](https://is.gd/rollup_chat) are usually the best places to start.
You can also create an [issue](issue) (protip: do a quick search first to see if someone else didn't ask the same question before!).
If you require technical assistance, [Stackoverflow](https://stackoverflow.com/questions/tagged/rollupjs) or [Discord](https://is.gd/rollup_chat) are usually the best places to start. You can also create an [issue](issue) (protip: do a quick search first to see if someone else didn't ask the same question before!).
## Credits
### Contributors
Thank you to all the people who have already contributed to rollup!
<a href="graphs/contributors"><img src="https://opencollective.com/rollup/contributors.svg?width=890" /></a>
Thank you to all the people who have already contributed to rollup! <a href="graphs/contributors"><img src="https://opencollective.com/rollup/contributors.svg?width=890" /></a>
### Backers
@ -49,20 +46,10 @@ Thank you to all our backers! [[Become a backer](https://opencollective.com/roll
<a href="https://opencollective.com/rollup#backers" target="_blank"><img src="https://opencollective.com/rollup/backers.svg?width=890"></a>
### Sponsors
Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/rollup#sponsor))
<a href="https://opencollective.com/rollup/sponsor/0/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/1/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/2/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/3/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/4/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/5/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/6/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/7/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/8/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/9/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/0/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/0/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/1/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/1/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/2/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/2/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/3/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/3/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/4/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/4/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/5/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/5/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/6/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/6/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/7/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/7/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/8/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/8/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/9/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/9/avatar.svg"></a>
<!-- This `CONTRIBUTING.md` is based on @nayafia's template https://github.com/nayafia/contributing-template -->

@ -2,20 +2,8 @@ The MIT License (MIT)
Copyright (c) 2017 [these people](https://github.com/rollup/rollup/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -108,8 +108,7 @@ To make sure your ES modules are immediately usable by tools that work with Comm
## Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/rollup/rollup/graphs/contributors"><img src="https://opencollective.com/rollup/contributors.svg?width=890" /></a>
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. <a href="https://github.com/rollup/rollup/graphs/contributors"><img src="https://opencollective.com/rollup/contributors.svg?width=890" /></a>
## Backers
@ -121,16 +120,7 @@ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/rollup#sponsor)]
<a href="https://opencollective.com/rollup/sponsor/0/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/1/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/2/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/3/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/4/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/5/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/6/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/7/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/8/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/9/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/rollup/sponsor/0/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/0/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/1/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/1/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/2/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/2/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/3/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/3/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/4/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/4/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/5/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/5/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/6/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/6/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/7/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/7/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/8/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/8/avatar.svg"></a> <a href="https://opencollective.com/rollup/sponsor/9/website" target="_blank"><img src="https://opencollective.com/rollup/sponsor/9/avatar.svg"></a>
## License

@ -16,11 +16,9 @@ This will make Rollup available as a global command line tool. You can also inst
### Quick start
Rollup can be used either through a [command line interface](guide/en/#command-line-reference) with an optional configuration file, or else through its [JavaScript API](guide/en/#javascript-api). Run `rollup --help` to see the available options and parameters.
Rollup can be used either through a [command line interface](guide/en/#command-line-reference) with an optional configuration file, or else through its [JavaScript API](guide/en/#javascript-api). Run `rollup --help` to see the available options and parameters.
> See [rollup-starter-lib](https://github.com/rollup/rollup-starter-lib) and
[rollup-starter-app](https://github.com/rollup/rollup-starter-app) to see
example library and application projects using Rollup
> See [rollup-starter-lib](https://github.com/rollup/rollup-starter-lib) and [rollup-starter-app](https://github.com/rollup/rollup-starter-app) to see example library and application projects using Rollup
These commands assume the entry point to your application is named `main.js`, and that you'd like all imports compiled into a single file named `bundle.js`.
@ -49,17 +47,17 @@ rollup main.js --file bundle.js --format umd --name "myBundle"
Developing software is usually easier if you break your project into smaller separate pieces, since that often removes unexpected interactions and dramatically reduces the complexity of the problems you'll need to solve, and simply writing smaller projects in the first place [isn't necessarily the answer](https://medium.com/@Rich_Harris/small-modules-it-s-not-quite-that-simple-3ca532d65de4). Unfortunately, JavaScript has not historically included this capability as a core feature in the language.
This finally changed with the ES6 revision of JavaScript, which includes a syntax for importing and exporting functions and data so they can be shared between separate scripts. The specification is now fixed, but it is only implemented in modern browsers and not finalised in Node.js. Rollup allows you to write your code using the new module system, and will then compile it back down to existing supported formats such as CommonJS modules, AMD modules, and IIFE-style scripts. This means that you get to *write future-proof code*, and you also get the tremendous benefits of…
This finally changed with the ES6 revision of JavaScript, which includes a syntax for importing and exporting functions and data so they can be shared between separate scripts. The specification is now fixed, but it is only implemented in modern browsers and not finalised in Node.js. Rollup allows you to write your code using the new module system, and will then compile it back down to existing supported formats such as CommonJS modules, AMD modules, and IIFE-style scripts. This means that you get to _write future-proof code_, and you also get the tremendous benefits of…
### Tree-Shaking
In addition to enabling the use of ES modules, Rollup also statically analyzes the code you are importing, and will exclude anything that isn't actually used. This allows you to build on top of existing tools and modules without adding extra dependencies or bloating the size of your project.
For example, with CommonJS, the *entire tool or library must be imported*.
For example, with CommonJS, the _entire tool or library must be imported_.
```js
// import the entire utils object with CommonJS
const utils = require( './utils' );
const utils = require('./utils');
const query = 'Rollup';
// use the ajax method of the utils object
utils.ajax(`https://api.example.com?search=${query}`).then(handleResponse);
@ -77,7 +75,6 @@ ajax(`https://api.example.com?search=${query}`).then(handleResponse);
Because Rollup includes the bare minimum, it results in lighter, faster, and less complicated libraries and applications. Since this approach can utilise explicit `import` and `export` statements, it is more effective than simply running an automated minifier to detect unused variables in the compiled output code.
### Compatibility
#### Importing CommonJS

@ -2,7 +2,7 @@
title: Command Line Interface
---
Rollup should typically be used from the command line. You can provide an optional Rollup configuration file to simplify command line usage and enable advanced Rollup functionality.
Rollup should typically be used from the command line. You can provide an optional Rollup configuration file to simplify command line usage and enable advanced Rollup functionality.
### Configuration Files
@ -35,7 +35,8 @@ Config files support the options listed below. Consult the [big list of options]
```javascript
// rollup.config.js
export default { // can be an array (for multiple inputs)
// can be an array (for multiple inputs)
export default {
// core input options
external,
input, // conditionally required
@ -60,7 +61,8 @@ export default { // can be an array (for multiple inputs)
experimentalCacheExpiry,
perf,
output: { // required (can be an array, for multiple outputs)
// required (can be an array, for multiple outputs)
output: {
// core output options
dir,
file,
@ -115,7 +117,7 @@ export default { // can be an array (for multiple inputs)
skipWrite,
exclude,
include
} | false
}
};
```
@ -124,25 +126,28 @@ You can export an **array** from your config file to build bundles from several
```javascript
// rollup.config.js (building more than one bundle)
export default [{
input: 'main-a.js',
output: {
file: 'dist/bundle-a.js',
format: 'cjs'
}
}, {
input: 'main-b.js',
output: [
{
file: 'dist/bundle-b1.js',
export default [
{
input: 'main-a.js',
output: {
file: 'dist/bundle-a.js',
format: 'cjs'
},
{
file: 'dist/bundle-b2.js',
format: 'es'
}
]
}];
},
{
input: 'main-b.js',
output: [
{
file: 'dist/bundle-b1.js',
format: 'cjs'
},
{
file: 'dist/bundle-b2.js',
format: 'es'
}
]
}
];
```
If you want to create your config asynchronously, Rollup can also handle a `Promise` which resolves to an object or an array.
@ -157,10 +162,7 @@ Similarly, you can do this as well:
```javascript
// rollup.config.js (Promise resolving an array)
export default Promise.all([
fetch('get-config-1'),
fetch('get-config-2')
])
export default Promise.all([fetch('get-config-1'), fetch('get-config-2')]);
```
To use Rollup with a configuration file, pass the `--config` or `-c` flags:
@ -187,7 +189,7 @@ export default commandLineArgs => {
return debugConfig;
}
return defaultConfig;
}
};
```
If you now run `rollup --config --configDebug`, the debug configuration will be used.
@ -219,27 +221,27 @@ Since Rollup ships with TypeScript typings, you can leverage your IDE's Intellis
*/
const config = {
// ...
}
};
export default config
export default config;
```
Alternatively you can use the `defineConfig` helper, which should provide Intellisense without the need for JSDoc annotations:
```javascript
// rollup.config.js
import { defineConfig } from 'rollup'
import { defineConfig } from 'rollup';
export default defineConfig({
// ...
})
});
```
Besides `RollupOptions` and the `defineConfig` helper that encapsulates this type, the following types can prove useful as well:
* `OutputOptions`: The `output` part of a config file
* `Plugin`: A plugin object that provides a `name` and some hooks. All hooks are fully typed to aid in plugin development.
* `PluginImpl`: A function that maps an options object to a plugin object. Most public Rollup plugins follow this pattern.
- `OutputOptions`: The `output` part of a config file
- `Plugin`: A plugin object that provides a `name` and some hooks. All hooks are fully typed to aid in plugin development.
- `PluginImpl`: A function that maps an options object to a plugin object. Most public Rollup plugins follow this pattern.
You can also directly write your config in TypeScript via the [`--configPlugin`](guide/en/#--configplugin-plugin) option.
@ -286,18 +288,19 @@ There are some potential gotchas when using `.mjs` on Node 13+:
- You will only get a default export from CommonJS plugins
- You may not be able to import JSON files such as your `package.json file`. There are two ways to go around this:
- run Rollup CLI via
```
node --experimental-json-modules ./node_modules/.bin/rollup --config
```
- create a CommonJS wrapper that requires the JSON file:
```js
// load-package.cjs
module.exports = require('./package.json');
// rollup.config.mjs
import pkg from './load-package.cjs';
...
@ -396,6 +399,7 @@ Use the specified plugin. There are several ways to specify plugins here:
```
The file should export a function returning a plugin object.
- Via the name of a plugin that is installed in a local or global `node_modules` folder:
```
@ -504,7 +508,7 @@ echo "export const foo = 42;" | rollup --format cjs --file out.js
When this file contains imports, Rollup will try to resolve them relative to the current working directory. When using a config file, Rollup will only use `stdin` as an entry point if the file name of the entry point is `-`. To read a non-entry-point file from stdin, just call it `-`, which is the file name that is used internally to reference `stdin`. I.e.
```js
import foo from "-";
import foo from '-';
```
in any file will prompt Rollup to try to read the imported file from `stdin` and assign the default export to `foo`. You can pass the [`--no-stdin`](guide/en/#--no-stdin) CLI flag to Rollup to treat `-` as a regular file name instead.

@ -250,25 +250,25 @@ const rollup = require('rollup');
// the provided config object has the same effect as passing "--format es"
// on the command line and will override the format of all outputs
loadConfigFile(path.resolve(__dirname, 'rollup.config.js'), { format: 'es' }).then(
async ({ options, warnings }) => {
// "warnings" wraps the default `onwarn` handler passed by the CLI.
// This prints all warnings up to this point:
console.log(`We currently have ${warnings.count} warnings`);
// This prints all deferred warnings
warnings.flush();
// options is an array of "inputOptions" objects with an additional "output"
// property that contains an array of "outputOptions".
// The following will generate all outputs for all inputs, and write them to disk the same
// way the CLI does it:
for (const optionsObj of options) {
const bundle = await rollup.rollup(optionsObj);
await Promise.all(optionsObj.output.map(bundle.write));
}
// You can also pass this directly to "rollup.watch"
rollup.watch(options);
}
async ({ options, warnings }) => {
// "warnings" wraps the default `onwarn` handler passed by the CLI.
// This prints all warnings up to this point:
console.log(`We currently have ${warnings.count} warnings`);
// This prints all deferred warnings
warnings.flush();
// options is an array of "inputOptions" objects with an additional "output"
// property that contains an array of "outputOptions".
// The following will generate all outputs for all inputs, and write them to disk the same
// way the CLI does it:
for (const optionsObj of options) {
const bundle = await rollup.rollup(optionsObj);
await Promise.all(optionsObj.output.map(bundle.write));
}
// You can also pass this directly to "rollup.watch"
rollup.watch(options);
}
);
```

@ -6,8 +6,7 @@ The following is intended as a lightweight reference for the module behaviors de
### Importing
Imported values cannot be reassigned, though imported objects and arrays *can* be mutated (and the exporting module, and any other importers, will be affected by the mutation). In that way, they behave similarly to `const` declarations.
Imported values cannot be reassigned, though imported objects and arrays _can_ be mutated (and the exporting module, and any other importers, will be affected by the mutation). In that way, they behave similarly to `const` declarations.
#### Named Imports
@ -28,7 +27,7 @@ import { something as somethingElse } from './module.js';
Import everything from the source module as an object which exposes all the source module's named exports as properties and methods.
```js
import * as module from './module.js'
import * as module from './module.js';
```
The `something` example from above would then be attached to the imported object as a property, e.g. `module.something`. If present, the default export can be accessed via `module.default`.
@ -56,9 +55,9 @@ This is useful for polyfills, or when the primary purpose of the imported code i
Import modules using the [dynamic import API](https://github.com/tc39/proposal-dynamic-import#import).
```js
import('./modules.js').then(({ default: DefaultExport, NamedExport })=> {
import('./modules.js').then(({ default: DefaultExport, NamedExport }) => {
// do something with modules.
})
});
```
This is useful for code-splitting applications and using modules on-the-fly.
@ -87,7 +86,6 @@ Export a value immediately upon declaration:
export const something = true;
```
#### Default Export
Export a single value as the source module's default export:
@ -100,10 +98,9 @@ This practice is only recommended if your source module only has one export.
It is bad practice to mix default and named exports in the same module, though it is allowed by the specification.
### How bindings work
ES modules export *live bindings*, not values, so values can be changed after they are initially imported as per [this demo](https://rollupjs.org/repl/?shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMCU3QiUyMGNvdW50JTJDJTIwaW5jcmVtZW50JTIwJTdEJTIwZnJvbSUyMCcuJTJGaW5jcmVtZW50ZXIuanMnJTNCJTVDbiU1Q25jb25zb2xlLmxvZyhjb3VudCklM0IlNUNuaW5jcmVtZW50KCklM0IlNUNuY29uc29sZS5sb2coY291bnQpJTNCJTIyJTdEJTJDJTdCJTIybmFtZSUyMiUzQSUyMmluY3JlbWVudGVyLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmV4cG9ydCUyMGxldCUyMGNvdW50JTIwJTNEJTIwMCUzQiU1Q24lNUNuZXhwb3J0JTIwZnVuY3Rpb24lMjBpbmNyZW1lbnQoKSUyMCU3QiU1Q24lNUN0Y291bnQlMjAlMkIlM0QlMjAxJTNCJTVDbiU3RCUyMiU3RCU1RCUyQyUyMm9wdGlvbnMlMjIlM0ElN0IlMjJmb3JtYXQlMjIlM0ElMjJjanMlMjIlMkMlMjJnbG9iYWxzJTIyJTNBJTdCJTdEJTJDJTIybW9kdWxlSWQlMjIlM0ElMjIlMjIlMkMlMjJuYW1lJTIyJTNBJTIybXlCdW5kbGUlMjIlN0QlMkMlMjJleGFtcGxlJTIyJTNBbnVsbCU3RA==):
ES modules export _live bindings_, not values, so values can be changed after they are initially imported as per [this demo](https://rollupjs.org/repl/?shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMCU3QiUyMGNvdW50JTJDJTIwaW5jcmVtZW50JTIwJTdEJTIwZnJvbSUyMCcuJTJGaW5jcmVtZW50ZXIuanMnJTNCJTVDbiU1Q25jb25zb2xlLmxvZyhjb3VudCklM0IlNUNuaW5jcmVtZW50KCklM0IlNUNuY29uc29sZS5sb2coY291bnQpJTNCJTIyJTdEJTJDJTdCJTIybmFtZSUyMiUzQSUyMmluY3JlbWVudGVyLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmV4cG9ydCUyMGxldCUyMGNvdW50JTIwJTNEJTIwMCUzQiU1Q24lNUNuZXhwb3J0JTIwZnVuY3Rpb24lMjBpbmNyZW1lbnQoKSUyMCU3QiU1Q24lNUN0Y291bnQlMjAlMkIlM0QlMjAxJTNCJTVDbiU3RCUyMiU3RCU1RCUyQyUyMm9wdGlvbnMlMjIlM0ElN0IlMjJmb3JtYXQlMjIlM0ElMjJjanMlMjIlMkMlMjJnbG9iYWxzJTIyJTNBJTdCJTdEJTJDJTIybW9kdWxlSWQlMjIlM0ElMjIlMjIlMkMlMjJuYW1lJTIyJTNBJTIybXlCdW5kbGUlMjIlN0QlMkMlMjJleGFtcGxlJTIyJTNBbnVsbCU3RA==):
```js
// incrementer.js

@ -4,7 +4,7 @@ title: Tutorial
### Creating Your First Bundle
*Before we begin, you'll need to have [Node.js](https://nodejs.org) installed so that you can use [NPM](https://npmjs.com). You'll also need to know how to access the [command line](https://www.codecademy.com/learn/learn-the-command-line) on your machine.*
_Before we begin, you'll need to have [Node.js](https://nodejs.org) installed so that you can use [NPM](https://npmjs.com). You'll also need to know how to access the [command line](https://www.codecademy.com/learn/learn-the-command-line) on your machine._
The easiest way to use Rollup is via the Command Line Interface (or CLI). For now, we'll install it globally (later on we'll learn how to install it locally to your project so that your build process is portable, but don't worry about that yet). Type this into the command line:
@ -28,7 +28,7 @@ mkdir -p my-rollup-project/src
cd my-rollup-project
```
First, we need an *entry point*. Paste this into a new file called `src/main.js`:
First, we need an _entry point_. Paste this into a new file called `src/main.js`:
```js
// src/main.js
@ -171,7 +171,7 @@ _Note: Once installed locally, both NPM and Yarn will resolve the dependency's b
So far, we've created a simple bundle from an entry point and a module imported via a relative path. As you build more complex bundles, you'll often need more flexibility importing modules installed with NPM, compiling code with Babel, working with JSON files and so on.
For that, we use *plugins*, which change the behaviour of Rollup at key points in the bundling process. A list of awesome plugins is maintained on [the Rollup Awesome List](https://github.com/rollup/awesome).
For that, we use _plugins_, which change the behaviour of Rollup at key points in the bundling process. A list of awesome plugins is maintained on [the Rollup Awesome List](https://github.com/rollup/awesome).
For this tutorial, we'll use [@rollup/plugin-json](https://github.com/rollup/plugins/tree/master/packages/json), which allows Rollup to import data from a JSON file.
@ -218,7 +218,7 @@ export default {
file: 'bundle.js',
format: 'cjs'
},
plugins: [ json() ]
plugins: [json()]
};
```
@ -227,9 +227,9 @@ Run Rollup with `npm run build`. The result should look like this:
```js
'use strict';
var version = "1.0.0";
var version = '1.0.0';
function main () {
function main() {
console.log('version ' + version);
}
@ -253,7 +253,7 @@ Edit your `rollup.config.js` file to add a second minified output. As format, we
```js
// rollup.config.js
import json from '@rollup/plugin-json';
import {terser} from 'rollup-plugin-terser';
import { terser } from 'rollup-plugin-terser';
export default {
input: 'src/main.js',
@ -269,17 +269,22 @@ export default {
plugins: [terser()]
}
],
plugins: [ json() ]
plugins: [json()]
};
```
Besides `bundle.js`, Rollup will now create a second file `bundle.min.js`:
```js
var version=function(){"use strict";var n="1.0.0";return function(){console.log("version "+n)}}();
var version = (function () {
'use strict';
var n = '1.0.0';
return function () {
console.log('version ' + n);
};
})();
```
### Code Splitting
For code splitting, there are cases where Rollup splits code into chunks automatically, like dynamic loading or multiple entry points, and there is a way to explicitly tell Rollup which modules to split into separate chunks via the [`output.manualChunks`](guide/en/#outputmanualchunks) option.
@ -313,14 +318,14 @@ If we do not use the `--dir` option, Rollup will again print the chunks to `stdo
//→ main.js:
'use strict';
function main () {
function main() {
Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) => console.log(foo));
}
module.exports = main;
//→ chunk-b8774ea3.js:
'use strict';
('use strict');
var foo = 'hello world!';
@ -351,25 +356,25 @@ will output
//→ main.js:
'use strict';
function main () {
function main() {
Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) => console.log(foo));
}
module.exports = main;
//→ main2.js:
'use strict';
('use strict');
var foo_js = require('./chunk-b8774ea3.js');
function main2 () {
function main2() {
console.log(foo_js.default);
}
module.exports = main2;
//→ chunk-b8774ea3.js:
'use strict';
('use strict');
var foo = 'hello world!';
@ -387,7 +392,7 @@ rollup src/main.js src/main2.js -f es -d dist
```
```html
<!doctype html>
<!DOCTYPE html>
<script type="module">
import main2 from './dist/main2.js';
main2();
@ -409,11 +414,10 @@ npm install --save-dev systemjs
And then load either or both entry points in an HTML page as needed:
```html
<!doctype html>
<!DOCTYPE html>
<script src="node_modules/systemjs/dist/s.min.js"></script>
<script>
System.import('./dist/main2.js')
.then(({ default: main }) => main());
System.import('./dist/main2.js').then(({ default: main }) => main());
</script>
```

@ -59,6 +59,7 @@ export default ({
### Properties
#### `name`
Type: `string`
The name of the plugin, for use in error messages and warnings.
@ -67,45 +68,41 @@ The name of the plugin, for use in error messages and warnings.
To interact with the build process, your plugin object includes 'hooks'. Hooks are functions which are called at various stages of the build. Hooks can affect how a build is run, provide information about a build, or modify a build once complete. There are different kinds of hooks:
* `async`: The hook may also return a promise resolving to the same type of value; otherwise, the hook is marked as `sync`.
* `first`: If several plugins implement this hook, the hooks are run sequentially until a hook returns a value other than `null` or `undefined`.
* `sequential`: If several plugins implement this hook, all of them will be run in the specified plugin order. If a hook is async, subsequent hooks of this kind will wait until the current hook is resolved.
* `parallel`: If several plugins implement this hook, all of them will be run in the specified plugin order. If a hook is async, subsequent hooks of this kind will be run in parallel and not wait for the current hook.
- `async`: The hook may also return a promise resolving to the same type of value; otherwise, the hook is marked as `sync`.
- `first`: If several plugins implement this hook, the hooks are run sequentially until a hook returns a value other than `null` or `undefined`.
- `sequential`: If several plugins implement this hook, all of them will be run in the specified plugin order. If a hook is async, subsequent hooks of this kind will wait until the current hook is resolved.
- `parallel`: If several plugins implement this hook, all of them will be run in the specified plugin order. If a hook is async, subsequent hooks of this kind will be run in parallel and not wait for the current hook.
Build hooks are run during the build phase, which is triggered by `rollup.rollup(inputOptions)`. They are mainly concerned with locating, providing and transforming input files before they are processed by Rollup. The first hook of the build phase is [`options`](guide/en/#options), the last one is always [`buildEnd`](guide/en/#buildend). If there is a build error, [`closeBundle`](guide/en/#closebundle) will be called after that.
Build hooks are run during the build phase, which is triggered by `rollup.rollup(inputOptions)`. They are mainly concerned with locating, providing and transforming input files before they are processed by Rollup. The first hook of the build phase is [`options`](guide/en/#options), the last one is always [`buildEnd`](guide/en/#buildend), unless there is a build error in which case [`closeBundle`](guide/en/#closebundle) will be called after that.
<!-- html:hooks-legend.html -->
<!-- mermaid:build-hooks.mmd -->
Additionally, in watch mode the [`watchChange`](guide/en/#watchchange) hook can be triggered at any time to notify a new run will be triggered once the current run has generated its outputs. Also, when watcher closes, the [`closeWatcher`](guide/en/#closewatcher) hook will be triggered.
See [Output Generation Hooks](guide/en/#output-generation-hooks) for hooks that run during the output generation phase to modify the generated output.
#### `buildEnd`
Type: `(error?: Error) => void`<br>
Kind: `async, parallel`<br>
Previous Hook: [`moduleParsed`](guide/en/#moduleparsed), [`resolveId`](guide/en/#resolveid) or [`resolveDynamicImport`](guide/en/#resolvedynamicimport).<br>
Next Hook: [`outputOptions`](guide/en/#outputoptions) in the output generation phase as this is the last hook of the build phase.
Type: `(error?: Error) => void`<br> Kind: `async, parallel`<br> Previous Hook: [`moduleParsed`](guide/en/#moduleparsed), [`resolveId`](guide/en/#resolveid) or [`resolveDynamicImport`](guide/en/#resolvedynamicimport).<br> Next Hook: [`outputOptions`](guide/en/#outputoptions) in the output generation phase as this is the last hook of the build phase.
Called when rollup has finished bundling, but before `generate` or `write` is called; you can also return a Promise. If an error occurred during the build, it is passed on to this hook.
#### `buildStart`
Type: `(options: InputOptions) => void`<br>
Kind: `async, parallel`<br>
Previous Hook: [`options`](guide/en/#options)<br>
Next Hook: [`resolveId`](guide/en/#resolveid) to resolve each entry point in parallel.
Type: `(options: InputOptions) => void`<br> Kind: `async, parallel`<br> Previous Hook: [`options`](guide/en/#options)<br> Next Hook: [`resolveId`](guide/en/#resolveid) to resolve each entry point in parallel.
Called on each `rollup.rollup` build. This is the recommended hook to use when you need access to the options passed to `rollup.rollup()` as it takes the transformations by all [`options`](guide/en/#options) hooks into account and also contains the right default values for unset options.
#### `closeWatcher`
Type: `() => void`<br>
Kind: `sync, sequential`<br>
Previous/Next Hook: This hook can be triggered at any time both during the build and the output generation phases. If that is the case, the current build will still proceed but no new [`watchChange`](guide/en/#watchchange) events will be triggered ever.
Type: `() => void`<br> Kind: `sync, sequential`<br> Previous/Next Hook: This hook can be triggered at any time both during the build and the output generation phases. If that is the case, the current build will still proceed but no new [`watchChange`](guide/en/#watchchange) events will be triggered ever.
Notifies a plugin when watcher process closes and all open resources should be closed too. This hook cannot be used by output plugins.
#### `load`
Type: `(id: string) => string | null | {code: string, map?: string | SourceMap, ast? : ESTree.Program, moduleSideEffects?: boolean | "no-treeshake" | null, syntheticNamedExports?: boolean | string | null, meta?: {[plugin: string]: any} | null}`<br>
Kind: `async, first`<br>
Previous Hook: [`resolveId`](guide/en/#resolveid) or [`resolveDynamicImport`](guide/en/#resolvedynamicimport) where the loaded id was resolved.<br>
Next Hook: [`transform`](guide/en/#transform) to transform the loaded file.
Type: `(id: string) => string | null | {code: string, map?: string | SourceMap, ast? : ESTree.Program, moduleSideEffects?: boolean | "no-treeshake" | null, syntheticNamedExports?: boolean | string | null, meta?: {[plugin: string]: any} | null}`<br> Kind: `async, first`<br> Previous Hook: [`resolveId`](guide/en/#resolveid) or [`resolveDynamicImport`](guide/en/#resolvedynamicimport) where the loaded id was resolved.<br> Next Hook: [`transform`](guide/en/#transform) to transform the loaded file.
Defines a custom loader. Returning `null` defers to other `load` functions (and eventually the default behavior of loading from the file system). To prevent additional parsing overhead in case e.g. this hook already used `this.parse` to generate an AST for some reason, this hook can optionally return a `{ code, ast, map }` object. The `ast` must be a standard ESTree AST with `start` and `end` properties for each node. If the transformation does not move code, you can preserve existing sourcemaps by setting `map` to `null`. Otherwise you might need to generate the source map. See [the section on source code transformations](#source-code-transformations).
@ -118,10 +115,8 @@ See [custom module meta-data](guide/en/#custom-module-meta-data) for how to use
You can use [`this.getModuleInfo`](guide/en/#thisgetmoduleinfomoduleid-string--moduleinfo--null) to find out the previous values of `moduleSideEffects`, `syntheticNamedExports` and `meta` inside this hook.
#### `moduleParsed`
Type: `(moduleInfo: ModuleInfo) => void`<br>
Kind: `async, parallel`<br>
Previous Hook: [`transform`](guide/en/#transform) where the currently handled file was transformed.<br>
NextHook: [`resolveId`](guide/en/#resolveid) and [`resolveDynamicImport`](guide/en/#resolvedynamicimport) to resolve all discovered static and dynamic imports in parallel if present, otherwise [`buildEnd`](guide/en/#buildend).
Type: `(moduleInfo: ModuleInfo) => void`<br> Kind: `async, parallel`<br> Previous Hook: [`transform`](guide/en/#transform) where the currently handled file was transformed.<br> NextHook: [`resolveId`](guide/en/#resolveid) and [`resolveDynamicImport`](guide/en/#resolvedynamicimport) to resolve all discovered static and dynamic imports in parallel if present, otherwise [`buildEnd`](guide/en/#buildend).
This hook is called each time a module has been fully parsed by Rollup. See [`this.getModuleInfo`](guide/en/#thisgetmoduleinfomoduleid-string--moduleinfo--null) for what information is passed to this hook.
@ -130,37 +125,32 @@ In contrast to the [`transform`](guide/en/#transform) hook, this hook is never c
Note that information about imported modules is not yet available in this hook, and information about importing modules may be incomplete as additional importers could be discovered later. If you need this information, use the [`buildEnd`](guide/en/#buildend) hook.
#### `options`
Type: `(options: InputOptions) => InputOptions | null`<br>
Kind: `async, sequential`<br>
Previous Hook: This is the first hook of the build phase.<br>
Next Hook: [`buildStart`](guide/en/#buildstart)
Type: `(options: InputOptions) => InputOptions | null`<br> Kind: `async, sequential`<br> Previous Hook: This is the first hook of the build phase.<br> Next Hook: [`buildStart`](guide/en/#buildstart)
Replaces or manipulates the options object passed to `rollup.rollup`. Returning `null` does not replace anything. If you just need to read the options, it is recommended to use the [`buildStart`](guide/en/#buildstart) hook as that hook has access to the options after the transformations from all `options` hooks have been taken into account.
This is the only hook that does not have access to most [plugin context](guide/en/#plugin-context) utility functions as it is run before rollup is fully configured.
#### `resolveDynamicImport`
Type: `(specifier: string | ESTree.Node, importer: string) => string | false | null | {id: string, external?: boolean}`<br>
Kind: `async, first`<br>
Previous Hook: [`moduleParsed`](guide/en/#moduleparsed) for the importing file.<br>
Next Hook: [`load`](guide/en/#load) if the hook resolved with an id that has not yet been loaded, [`resolveId`](guide/en/#resolveid) if the dynamic import contains a string and was not resolved by the hook, otherwise [`buildEnd`](guide/en/#buildend).
Type: `(specifier: string | ESTree.Node, importer: string) => string | false | null | {id: string, external?: boolean}`<br> Kind: `async, first`<br> Previous Hook: [`moduleParsed`](guide/en/#moduleparsed) for the importing file.<br> Next Hook: [`load`](guide/en/#load) if the hook resolved with an id that has not yet been loaded, [`resolveId`](guide/en/#resolveid) if the dynamic import contains a string and was not resolved by the hook, otherwise [`buildEnd`](guide/en/#buildend).
Defines a custom resolver for dynamic imports. Returning `false` signals that the import should be kept as it is and not be passed to other resolvers thus making it external. Similar to the [`resolveId`](guide/en/#resolveid) hook, you can also return an object to resolve the import to a different id while marking it as external at the same time.
In case a dynamic import is passed a string as argument, a string returned from this hook will be interpreted as an existing module id while returning `null` will defer to other resolvers and eventually to `resolveId` .
In case a dynamic import is not passed a string as argument, this hook gets access to the raw AST nodes to analyze and behaves slightly different in the following ways:
- If all plugins return `null`, the import is treated as `external` without a warning.
- If a string is returned, this string is *not* interpreted as a module id but is instead used as a replacement for the import argument. It is the responsibility of the plugin to make sure the generated code is valid.
- If a string is returned, this string is _not_ interpreted as a module id but is instead used as a replacement for the import argument. It is the responsibility of the plugin to make sure the generated code is valid.
- To resolve such an import to an existing module, you can still return an object `{id, external}`.
Note that the return value of this hook will not be passed to `resolveId` afterwards; if you need access to the static resolution algorithm, you can use [`this.resolve(source, importer)`](guide/en/#thisresolvesource-string-importer-string-options-skipself-boolean-custom-plugin-string-any--promiseid-string-external-boolean--absolute-modulesideeffects-boolean--no-treeshake-syntheticnamedexports-boolean--string-meta-plugin-string-any--null) on the plugin context.
#### `resolveId`
Type: `(source: string, importer: string | undefined, options: {custom?: {[plugin: string]: any}) => string | false | null | {id: string, external?: boolean | "relative" | "absolute", moduleSideEffects?: boolean | "no-treeshake" | null, syntheticNamedExports?: boolean | string | null, meta?: {[plugin: string]: any} | null}`<br>
Kind: `async, first`<br>
Previous Hook: [`buildStart`](guide/en/#buildstart) if we are resolving an entry point, [`moduleParsed`](guide/en/#moduleparsed) if we are resolving an import, or as fallback for [`resolveDynamicImport`](guide/en/#resolvedynamicimport). Additionally this hook can be triggered during the build phase from plugin hooks by calling [`this.emitFile`](guide/en/#thisemitfileemittedfile-emittedchunk--emittedasset--string) to emit an entry point or at any time by calling [`this.resolve`](guide/en/#thisresolvesource-string-importer-string-options-skipself-boolean-custom-plugin-string-any--promiseid-string-external-boolean--absolute-modulesideeffects-boolean--no-treeshake-syntheticnamedexports-boolean--string-meta-plugin-string-any--null) to manually resolve an id.<br>
Next Hook: [`load`](guide/en/#load) if the resolved id that has not yet been loaded, otherwise [`buildEnd`](guide/en/#buildend).
Type: `(source: string, importer: string | undefined, options: {custom?: {[plugin: string]: any}) => string | false | null | {id: string, external?: boolean | "relative" | "absolute", moduleSideEffects?: boolean | "no-treeshake" | null, syntheticNamedExports?: boolean | string | null, meta?: {[plugin: string]: any} | null}`<br> Kind: `async, first`<br> Previous Hook: [`buildStart`](guide/en/#buildstart) if we are resolving an entry point, [`moduleParsed`](guide/en/#moduleparsed) if we are resolving an import, or as fallback for [`resolveDynamicImport`](guide/en/#resolvedynamicimport). Additionally this hook can be triggered during the build phase from plugin hooks by calling [`this.emitFile`](guide/en/#thisemitfileemittedfile-emittedchunk--emittedasset--string) to emit an entry point or at any time by calling [`this.resolve`](guide/en/#thisresolvesource-string-importer-string-options-skipself-boolean-custom-plugin-string-any--promiseid-string-external-boolean--absolute-modulesideeffects-boolean--no-treeshake-syntheticnamedexports-boolean--string-meta-plugin-string-any--null) to manually resolve an id.<br> Next Hook: [`load`](guide/en/#load) if the resolved id that has not yet been loaded, otherwise [`buildEnd`](guide/en/#buildend).
Defines a custom resolver. A resolver can be useful for e.g. locating third-party dependencies. Here `source` is the importee exactly as it is written in the import statement, i.e. for
@ -208,7 +198,7 @@ resolveId(source) {
}
```
If `external` is `true`, then absolute ids will be converted to relative ids based on the user's choice for the [`makeAbsoluteExternalsRelative`](guide/en/#makeabsoluteexternalsrelative) option. This choice can be overridden by passing either `external: "relative"` to always convert an absolute id to a relative id or `external: "absolute"` to keep it as an absolute id. When returning an object, relative external ids, i.e. ids starting with `./` or `../`, will *not* be internally converted to an absolute id and converted back to a relative id in the output, but are instead included in the output unchanged. If you want relative ids to be renormalised and deduplicated instead, return an absolute file system location as `id` and choose `external: "relative"`.
If `external` is `true`, then absolute ids will be converted to relative ids based on the user's choice for the [`makeAbsoluteExternalsRelative`](guide/en/#makeabsoluteexternalsrelative) option. This choice can be overridden by passing either `external: "relative"` to always convert an absolute id to a relative id or `external: "absolute"` to keep it as an absolute id. When returning an object, relative external ids, i.e. ids starting with `./` or `../`, will _not_ be internally converted to an absolute id and converted back to a relative id in the output, but are instead included in the output unchanged. If you want relative ids to be renormalised and deduplicated instead, return an absolute file system location as `id` and choose `external: "relative"`.
If `false` is returned for `moduleSideEffects` in the first hook that resolves a module id and no other module imports anything from this module, then this module will not be included even if the module would have side-effects. If `true` is returned, Rollup will use its default algorithm to include all statements in the module that have side-effects (such as modifying a global or exported variable). If `"no-treeshake"` is returned, treeshaking will be turned off for this module and it will also be included in one of the generated chunks even if it is empty. If `null` is returned or the flag is omitted, then `moduleSideEffects` will be determined by the `treeshake.moduleSideEffects` option or default to `true`. The `load` and `transform` hooks can override this.
@ -219,10 +209,8 @@ See [custom module meta-data](guide/en/#custom-module-meta-data) for how to use
When triggering this hook from a plugin via [`this.resolve(source, importer, options)`](guide/en/#thisresolvesource-string-importer-string-options-skipself-boolean-custom-plugin-string-any--promiseid-string-external-boolean--absolute-modulesideeffects-boolean--no-treeshake-syntheticnamedexports-boolean--string-meta-plugin-string-any--null), it is possible to pass a custom options object to this hook. While this object will be passed unmodified, plugins should follow the convention of adding a `custom` property with an object where the keys correspond to the names of the plugins that the options are intended for. For details see [custom resolver options](guide/en/#custom-resolver-options).
#### `transform`
Type: `(code: string, id: string) => string | null | {code?: string, map?: string | SourceMap, ast? : ESTree.Program, moduleSideEffects?: boolean | "no-treeshake" | null, syntheticNamedExports?: boolean | string | null, meta?: {[plugin: string]: any} | null}`<br>
Kind: `async, sequential`<br>
Previous Hook: [`load`](guide/en/#load) where the currently handled file was loaded.<br>
NextHook: [`moduleParsed`](guide/en/#moduleparsed) once the file has been processed and parsed.
Type: `(code: string, id: string) => string | null | {code?: string, map?: string | SourceMap, ast? : ESTree.Program, moduleSideEffects?: boolean | "no-treeshake" | null, syntheticNamedExports?: boolean | string | null, meta?: {[plugin: string]: any} | null}`<br> Kind: `async, sequential`<br> Previous Hook: [`load`](guide/en/#load) where the currently handled file was loaded.<br> NextHook: [`moduleParsed`](guide/en/#moduleparsed) once the file has been processed and parsed.
Can be used to transform individual modules. To prevent additional parsing overhead in case e.g. this hook already used `this.parse` to generate an AST for some reason, this hook can optionally return a `{ code, ast, map }` object. The `ast` must be a standard ESTree AST with `start` and `end` properties for each node. If the transformation does not move code, you can preserve existing sourcemaps by setting `map` to `null`. Otherwise you might need to generate the source map. See [the section on source code transformations](#source-code-transformations).
@ -245,11 +233,10 @@ See [custom module meta-data](guide/en/#custom-module-meta-data) for how to use
You can use [`this.getModuleInfo`](guide/en/#thisgetmoduleinfomoduleid-string--moduleinfo--null) to find out the previous values of `moduleSideEffects`, `syntheticNamedExports` and `meta` inside this hook.
#### `watchChange`
Type: `watchChange: (id: string, change: {event: 'create' | 'update' | 'delete'}) => void`<br>
Kind: `sync, sequential`<br>
Previous/Next Hook: This hook can be triggered at any time both during the build and the output generation phases. If that is the case, the current build will still proceed but a new build will be scheduled to start once the current build has completed, starting again with [`options`](guide/en/#options).
Notifies a plugin whenever rollup has detected a change to a monitored file in `--watch` mode. This hook cannot be used by output plugins. Second argument contains additional details of change event.
Type: `watchChange: (id: string, change: {event: 'create' | 'update' | 'delete'}) => void`<br> Kind: `sync, sequential`<br> Previous/Next Hook: This hook can be triggered at any time both during the build and the output generation phases. If that is the case, the current build will still proceed but a new build will be scheduled to start once the current build has completed, starting again with [`options`](guide/en/#options).
Notifies a plugin whenever rollup has detected a change to a monitored file in `--watch` mode. This hook cannot be used by output plugins. Second argument contains additional details of change event.
### Output Generation Hooks
@ -257,13 +244,14 @@ Output generation hooks can provide information about a generated bundle and mod
The first hook of the output generation phase is [`outputOptions`](guide/en/#outputoptions), the last one is either [`generateBundle`](guide/en/#generatebundle) if the output was successfully generated via `bundle.generate(...)`, [`writeBundle`](guide/en/#writebundle) if the output was successfully generated via `bundle.write(...)`, or [`renderError`](guide/en/#rendererror) if an error occurred at any time during the output generation.
<!-- html:hooks-legend.html -->
<!-- mermaid:output-generation-hooks.mmd -->
Additionally, [`closeBundle`](guide/en/#closebundle) can be called as the very last hook, but it is the responsibility of the User to manually call [`bundle.close()`](guide/en/#rolluprollup) to trigger this. The CLI will always make sure this is the case.
#### `augmentChunkHash`
Type: `(chunkInfo: ChunkInfo) => string`<br>
Kind: `sync, sequential`<br>
Previous Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.<br>
Next Hook: [`resolveFileUrl`](guide/en/#resolvefileurl) for each use of `import.meta.ROLLUP_FILE_URL_referenceId` and [`resolveImportMeta`](guide/en/#resolveimportmeta) for all other accesses to `import.meta`.
Type: `(chunkInfo: ChunkInfo) => string`<br> Kind: `sync, sequential`<br> Previous Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.<br> Next Hook: [`resolveFileUrl`](guide/en/#resolvefileurl) for each use of `import.meta.ROLLUP_FILE_URL_referenceId` and [`resolveImportMeta`](guide/en/#resolveimportmeta) for all other accesses to `import.meta`.
Can be used to augment the hash of individual chunks. Called for each Rollup output chunk. Returning a falsy value will not modify the hash. Truthy values will be passed to [`hash.update`](https://nodejs.org/dist/latest-v12.x/docs/api/crypto.html#crypto_hash_update_data_inputencoding). The `chunkInfo` is a reduced version of the one in [`generateBundle`](guide/en/#generatebundle) without properties that rely on file names.
@ -279,35 +267,28 @@ augmentChunkHash(chunkInfo) {
```
#### `banner`
Type: `string | (() => string)`<br>
Kind: `async, parallel`<br>
Previous Hook: [`renderStart`](guide/en/#renderstart)<br>
Next Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
Type: `string | (() => string)`<br> Kind: `async, parallel`<br> Previous Hook: [`renderStart`](guide/en/#renderstart)<br> Next Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
Cf. [`output.banner/output.footer`](guide/en/#outputbanneroutputfooter).
#### `closeBundle`
Type: `closeBundle: () => Promise<void> | void`<br>
Kind: `async, parallel`<br>
Previous Hook: [`buildEnd`](guide/en/#buildend) if there was a build error, otherwise when [`bundle.close()`](guide/en/#rolluprollup) is called, in which case this would be the last hook to be triggered.
Type: `closeBundle: () => Promise<void> | void`<br> Kind: `async, parallel`<br> Previous Hook: [`buildEnd`](guide/en/#buildend) if there was a build error, otherwise when [`bundle.close()`](guide/en/#rolluprollup) is called, in which case this would be the last hook to be triggered.
Can be used to clean up any external service that may be running. Rollup's CLI will make sure this hook is called after each run, but it is the responsibility of users of the JavaScript API to manually call `bundle.close()` once they are done generating bundles. For that reason, any plugin relying on this feature should carefully mention this in its documentation.
If a plugin wants to retain resources across builds in watch mode, they can check for [`this.meta.watchMode`](guide/en/#thismeta-rollupversion-string-watchmode-boolean) in this hook and perform the necessary cleanup for watch mode in [`closeWatcher`](guide/en/#closewatcher).
#### `footer`
Type: `string | (() => string)`<br>
Kind: `async, parallel`<br>
Previous Hook: [`renderStart`](guide/en/#renderstart)<br>
Next Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
Type: `string | (() => string)`<br> Kind: `async, parallel`<br> Previous Hook: [`renderStart`](guide/en/#renderstart)<br> Next Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
Cf. [`output.banner/output.footer`](guide/en/#outputbanneroutputfooter).
#### `generateBundle`
Type: `(options: OutputOptions, bundle: { [fileName: string]: AssetInfo | ChunkInfo }, isWrite: boolean) => void`<br>
Kind: `async, sequential`<br>
Previous Hook: [`renderChunk`](guide/en/#renderchunk) for each chunk.<br>
Next Hook: [`writeBundle`](guide/en/#writebundle) if the output was generated via `bundle.write(...)`, otherwise this is the last hook of the output generation phase and may again be followed by [`outputOptions`](guide/en/#outputoptions) if another output is generated.
Type: `(options: OutputOptions, bundle: { [fileName: string]: AssetInfo | ChunkInfo }, isWrite: boolean) => void`<br> Kind: `async, sequential`<br> Previous Hook: [`renderChunk`](guide/en/#renderchunk) for each chunk.<br> Next Hook: [`writeBundle`](guide/en/#writebundle) if the output was generated via `bundle.write(...)`, otherwise this is the last hook of the output generation phase and may again be followed by [`outputOptions`](guide/en/#outputoptions) if another output is generated.
Called at the end of `bundle.generate()` or immediately before the files are written in `bundle.write()`. To modify the files after they have been written, use the [`writeBundle`](guide/en/#writebundle) hook. `bundle` provides the full list of files being written or generated along with their details:
@ -349,45 +330,35 @@ Called at the end of `bundle.generate()` or immediately before the files are wri
}
```
You can prevent files from being emitted by deleting them from the bundle object in this hook. To emit additional files, use the [`this.emitFile`](guide/en/#thisemitfileemittedfile-emittedchunk--emittedasset--string) plugin context function.
You can prevent files from being emitted by deleting them from the bundle object in this hook. To emit additional files, use the [`this.emitFile`](guide/en/#thisemitfileemittedfile-emittedchunk--emittedasset--string) plugin context function.
#### `intro`
Type: `string | (() => string)`<br>
Kind: `async, parallel`<br>
Previous Hook: [`renderStart`](guide/en/#renderstart)<br>
Next Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
Type: `string | (() => string)`<br> Kind: `async, parallel`<br> Previous Hook: [`renderStart`](guide/en/#renderstart)<br> Next Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
Cf. [`output.intro/output.outro`](guide/en/#outputintrooutputoutro).
#### `outputOptions`
Type: `(outputOptions: OutputOptions) => OutputOptions | null`<br>
Kind: `sync, sequential`<br>
Previous Hook: [`buildEnd`](guide/en/#buildend) if this is the first time an output is generated, otherwise either [`generateBundle`](guide/en/#generatebundle), [`writeBundle`](guide/en/#writebundle) or [`renderError`](guide/en/#rendererror) depending on the previously generated output. This is the first hook of the output generation phase.<br>
Next Hook: [`renderStart`](guide/en/#renderstart).
Type: `(outputOptions: OutputOptions) => OutputOptions | null`<br> Kind: `sync, sequential`<br> Previous Hook: [`buildEnd`](guide/en/#buildend) if this is the first time an output is generated, otherwise either [`generateBundle`](guide/en/#generatebundle), [`writeBundle`](guide/en/#writebundle) or [`renderError`](guide/en/#rendererror) depending on the previously generated output. This is the first hook of the output generation phase.<br> Next Hook: [`renderStart`](guide/en/#renderstart).
Replaces or manipulates the output options object passed to `bundle.generate()` or `bundle.write()`. Returning `null` does not replace anything. If you just need to read the output options, it is recommended to use the [`renderStart`](guide/en/#renderstart) hook as this hook has access to the output options after the transformations from all `outputOptions` hooks have been taken into account.
#### `outro`
Type: `string | (() => string)`<br>
Kind: `async, parallel`<br>
Previous Hook: [`renderStart`](guide/en/#renderstart)<br>
Next Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
Type: `string | (() => string)`<br> Kind: `async, parallel`<br> Previous Hook: [`renderStart`](guide/en/#renderstart)<br> Next Hook: [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
Cf. [`output.intro/output.outro`](guide/en/#outputintrooutputoutro).
#### `renderChunk`
Type: `(code: string, chunk: ChunkInfo, options: OutputOptions) => string | { code: string, map: SourceMap } | null`<br>
Kind: `async, sequential`<br>
Previous Hook: [`resolveFileUrl`](guide/en/#resolvefileurl) for each use of `import.meta.ROLLUP_FILE_URL_referenceId` and [`resolveImportMeta`](guide/en/#resolveimportmeta) for all other accesses to `import.meta`.<br>
Next Hook: [`generateBundle`](guide/en/#generatebundle).
Type: `(code: string, chunk: ChunkInfo, options: OutputOptions) => string | { code: string, map: SourceMap } | null`<br> Kind: `async, sequential`<br> Previous Hook: [`resolveFileUrl`](guide/en/#resolvefileurl) for each use of `import.meta.ROLLUP_FILE_URL_referenceId` and [`resolveImportMeta`](guide/en/#resolveimportmeta) for all other accesses to `import.meta`.<br> Next Hook: [`generateBundle`](guide/en/#generatebundle).
Can be used to transform individual chunks. Called for each Rollup output chunk file. Returning `null` will apply no transformations.
#### `renderDynamicImport`
Type: `({format: string, moduleId: string, targetModuleId: string | null, customResolution: string | null}) => {left: string, right: string} | null`<br>
Kind: `sync, first`<br>
Previous Hook: [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro), [`outro`](guide/en/#outro).<br>
Next Hook: [`augmentChunkHash`](guide/en/#augmentchunkhash) for each chunk that would contain a hash in the file name.
Type: `({format: string, moduleId: string, targetModuleId: string | null, customResolution: string | null}) => {left: string, right: string} | null`<br> Kind: `sync, first`<br> Previous Hook: [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro), [`outro`](guide/en/#outro).<br> Next Hook: [`augmentChunkHash`](guide/en/#augmentchunkhash) for each chunk that would contain a hash in the file name.
This hook provides fine-grained control over how dynamic imports are rendered by providing replacements for the code to the left (`import(`) and right (`)`) of the argument of the import expression. Returning `null` defers to other hooks of this type and ultimately renders a format-specific default.
@ -403,7 +374,7 @@ const plugin = {
return {
left: 'dynamicImportPolyfill(',
right: ', import.meta.url)'
}
};
}
};
@ -424,11 +395,12 @@ const plugin = {
if (specifier === 'esm-lib') return false;
return null;
},
renderDynamicImport({targetModuleId}) {
if (targetModuleId === 'esm-lib')
return {
left: 'import(',
right: ')'
renderDynamicImport({ targetModuleId }) {
if (targetModuleId === 'esm-lib') {
return {
left: 'import(',
right: ')'
};
}
}
};
@ -437,26 +409,20 @@ const plugin = {
Note that when this hook rewrites dynamic imports in non-ES formats, no interop code to make sure that e.g. the default export is available as `.default` is generated. It is the responsibility of the plugin to make sure the rewritten dynamic import returns a Promise that resolves to a proper namespace object.
#### `renderError`
Type: `(error: Error) => void`<br>
Kind: `async, parallel`<br>
Previous Hook: Any hook from [`renderStart`](guide/en/#renderstart) to [`renderChunk`](guide/en/#renderchunk).<br>
Next Hook: If it is called, this is the last hook of the output generation phase and may again be followed by [`outputOptions`](guide/en/#outputoptions) if another output is generated.
Type: `(error: Error) => void`<br> Kind: `async, parallel`<br> Previous Hook: Any hook from [`renderStart`](guide/en/#renderstart) to [`renderChunk`](guide/en/#renderchunk).<br> Next Hook: If it is called, this is the last hook of the output generation phase and may again be followed by [`outputOptions`](guide/en/#outputoptions) if another output is generated.
Called when rollup encounters an error during `bundle.generate()` or `bundle.write()`. The error is passed to this hook. To get notified when generation completes successfully, use the `generateBundle` hook.
#### `renderStart`
Type: `(outputOptions: OutputOptions, inputOptions: InputOptions) => void`<br>
Kind: `async, parallel`<br>
Previous Hook: [`outputOptions`](guide/en/#outputoptions)<br>
Next Hook: [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro) and [`outro`](guide/en/#outro) run in parallel.
Type: `(outputOptions: OutputOptions, inputOptions: InputOptions) => void`<br> Kind: `async, parallel`<br> Previous Hook: [`outputOptions`](guide/en/#outputoptions)<br> Next Hook: [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro) and [`outro`](guide/en/#outro) run in parallel.
Called initially each time `bundle.generate()` or `bundle.write()` is called. To get notified when generation has completed, use the `generateBundle` and `renderError` hooks. This is the recommended hook to use when you need access to the output options passed to `bundle.generate()` or `bundle.write()` as it takes the transformations by all [`outputOptions`](guide/en/#outputoptions) hooks into account and also contains the right default values for unset options. It also receives the input options passed to `rollup.rollup()` so that plugins that can be used as output plugins, i.e. plugins that only use `generate` phase hooks, can get access to them.
#### `resolveFileUrl`
Type: `({chunkId: string, fileName: string, format: string, moduleId: string, referenceId: string, relativePath: string}) => string | null`<br>
Kind: `sync, first`<br>
Previous Hook: [`augmentChunkHash`](guide/en/#augmentchunkhash) for each chunk that would contain a hash in the file name.<br>
Next Hook: [`renderChunk`](guide/en/#renderchunk) for each chunk.
Type: `({chunkId: string, fileName: string, format: string, moduleId: string, referenceId: string, relativePath: string}) => string | null`<br> Kind: `sync, first`<br> Previous Hook: [`augmentChunkHash`](guide/en/#augmentchunkhash) for each chunk that would contain a hash in the file name.<br> Next Hook: [`renderChunk`](guide/en/#renderchunk) for each chunk.
Allows to customize how Rollup resolves URLs of files that were emitted by plugins via `this.emitFile`. By default, Rollup will generate code for `import.meta.ROLLUP_FILE_URL_referenceId` that should correctly generate absolute URLs of emitted files independent of the output format and the host system where the code is deployed.
@ -481,16 +447,14 @@ resolveFileUrl({fileName}) {
```
#### `resolveImportMeta`
Type: `(property: string | null, {chunkId: string, moduleId: string, format: string}) => string | null`<br>
Kind: `sync, first`<br>
Previous Hook: [`augmentChunkHash`](guide/en/#augmentchunkhash) for each chunk that would contain a hash in the file name.<br>
Next Hook: [`renderChunk`](guide/en/#renderchunk) for each chunk.
Type: `(property: string | null, {chunkId: string, moduleId: string, format: string}) => string | null`<br> Kind: `sync, first`<br> Previous Hook: [`augmentChunkHash`](guide/en/#augmentchunkhash) for each chunk that would contain a hash in the file name.<br> Next Hook: [`renderChunk`](guide/en/#renderchunk) for each chunk.
Allows to customize how Rollup handles `import.meta` and `import.meta.someProperty`, in particular `import.meta.url`. In ES modules, `import.meta` is an object and `import.meta.url` contains the URL of the current module, e.g. `http://server.net/bundle.js` for browsers or `file:///path/to/bundle.js` in Node.
By default for formats other than ES modules, Rollup replaces `import.meta.url` with code that attempts to match this behaviour by returning the dynamic URL of the current chunk. Note that all formats except CommonJS and UMD assume that they run in a browser environment where `URL` and `document` are available. For other properties, `import.meta.someProperty` is replaced with `undefined` while `import.meta` is replaced with an object containing a `url` property.
This behaviour can be changed—also for ES modules—via this hook. For each occurrence of `import.meta<.someProperty>`, this hook is called with the name of the property or `null` if `import.meta` is accessed directly. For example, the following code will resolve `import.meta.url` using the relative path of the original module to the current working directory and again resolve this path against the base URL of the current document at runtime:
This behaviour can be changed—also for ES modules—via this hook. For each occurrence of `import.meta<.someProperty>`, this hook is called with the name of the property or `null` if `import.meta` is accessed directly. For example, the following code will resolve `import.meta.url` using the relative path of the original module to the current working directory and again resolve this path against the base URL of the current document at runtime:
```javascript
// rollup.config.js
@ -505,10 +469,8 @@ resolveImportMeta(property, {moduleId}) {
Note that since this hook has access to the filename of the current chunk, its return value will not be considered when generating the hash of this chunk.
#### `writeBundle`
Type: `(options: OutputOptions, bundle: { [fileName: string]: AssetInfo | ChunkInfo }) => void`<br>
Kind: `async, parallel`<br>
Previous Hook: [`generateBundle`](guide/en/#generatebundle)<br>
Next Hook: If it is called, this is the last hook of the output generation phase and may again be followed by [`outputOptions`](guide/en/#outputoptions) if another output is generated.
Type: `(options: OutputOptions, bundle: { [fileName: string]: AssetInfo | ChunkInfo }) => void`<br> Kind: `async, parallel`<br> Previous Hook: [`generateBundle`](guide/en/#generatebundle)<br> Next Hook: If it is called, this is the last hook of the output generation phase and may again be followed by [`outputOptions`](guide/en/#outputoptions) if another output is generated.
Called only at the end of `bundle.write()` once all files have been written. Similar to the [`generateBundle`](guide/en/#generatebundle) hook, `bundle` provides the full list of files being written along with their details.
@ -563,7 +525,7 @@ You can reference the URL of an emitted file in any code returned by a [`load`](
The generated code that replaces `import.meta.ROLLUP_FILE_URL_referenceId` can be customized via the [`resolveFileUrl`](guide/en/#resolvefileurl) plugin hook. You can also use [`this.getFileName(referenceId)`](guide/en/#thisgetfilenamereferenceid-string--string) to determine the file name as soon as it is available
If the `type` is *`chunk`*, then this emits a new chunk with the given module `id` as entry point. To resolve it, the `id` will be passed through build hooks just like regular entry points, starting with [`resolveId`](guide/en/#resolveid). If an `importer` is provided, this acts as the second parameter of `resolveId` and is important to properly resolve relative paths. If it is not provided, paths will be resolved relative to the current working directory. If a value for `preserveSignature` is provided, this will override [`preserveEntrySignatures`](guide/en/#preserveentrysignatures) for this particular chunk.
If the `type` is _`chunk`_, then this emits a new chunk with the given module `id` as entry point. To resolve it, the `id` will be passed through build hooks just like regular entry points, starting with [`resolveId`](guide/en/#resolveid). If an `importer` is provided, this acts as the second parameter of `resolveId` and is important to properly resolve relative paths. If it is not provided, paths will be resolved relative to the current working directory. If a value for `preserveSignature` is provided, this will override [`preserveEntrySignatures`](guide/en/#preserveentrysignatures) for this particular chunk.
This will not result in duplicate modules in the graph, instead if necessary, existing chunks will be split or a facade chunk with reexports will be created. Chunks with a specified `fileName` will always generate separate chunks while other emitted chunks may be deduplicated with existing chunks even if the `name` does not match. If such a chunk is not deduplicated, the [`output.chunkFileNames`](guide/en/#outputchunkfilenames) name pattern will be used.
@ -591,20 +553,23 @@ function generateHtml() {
});
},
generateBundle() {
this.emitFile({type: 'asset', fileName: 'index.html', source: `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="${this.getFileName(ref1)}" type="module"></script>
<script src="${this.getFileName(ref2)}" type="module"></script>
<script src="${this.getFileName(ref3)}" type="module"></script>
</body>
</html>
`})
this.emitFile({
type: 'asset',
fileName: 'index.html',
source: `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="${this.getFileName(ref1)}" type="module"></script>
<script src="${this.getFileName(ref2)}" type="module"></script>
<script src="${this.getFileName(ref3)}" type="module"></script>
</body>
</html>`
});
}
};
}
@ -612,9 +577,7 @@ function generateHtml() {
export default {
input: [],
preserveEntrySignatures: false,
plugins: [
generateHtml(),
],
plugins: [generateHtml()],
output: {
format: 'es',
dir: 'dist'
@ -626,7 +589,7 @@ If there are no dynamic imports, this will create exactly three chunks where the
Note that even though any module id can be used in `implicitlyLoadedAfterOneOf`, Rollup will throw an error if such an id cannot be uniquely associated with a chunk, e.g. because the `id` cannot be reached implicitly or explicitly from the existing static entry points, or because the file is completely tree-shaken. Using only entry points, either defined by the user or of previously emitted chunks, will always work, though.
If the `type` is *`asset`*, then this emits an arbitrary new file with the given `source` as content. It is possible to defer setting the `source` via [`this.setAssetSource(referenceId, source)`](guide/en/#thissetassetsourcereferenceid-string-source-string--uint8array--void) to a later time to be able to reference a file during the build phase while setting the source separately for each output during the generate phase. Assets with a specified `fileName` will always generate separate files while other emitted assets may be deduplicated with existing assets if they have the same source even if the `name` does not match. If such an asset is not deduplicated, the [`output.assetFileNames`](guide/en/#outputassetfilenames) name pattern will be used.
If the `type` is _`asset`_, then this emits an arbitrary new file with the given `source` as content. It is possible to defer setting the `source` via [`this.setAssetSource(referenceId, source)`](guide/en/#thissetassetsourcereferenceid-string-source-string--uint8array--void) to a later time to be able to reference a file during the build phase while setting the source separately for each output during the generate phase. Assets with a specified `fileName` will always generate separate files while other emitted assets may be deduplicated with existing assets if they have the same source even if the `name` does not match. If such an asset is not deduplicated, the [`output.assetFileNames`](guide/en/#outputassetfilenames) name pattern will be used.
#### `this.error(error: string | Error, position?: number | { column: number; line: number }) => never`
@ -645,7 +608,9 @@ Get the file name of a chunk or asset that has been emitted via [`this.emitFile`
Returns an `Iterator` that gives access to all module ids in the current graph. It can be iterated via
```js
for (const moduleId of this.getModuleIds()) { /* ... */ }
for (const moduleId of this.getModuleIds()) {
/* ... */
}
```
or converted into an Array via `Array.from(this.getModuleIds())`.
@ -673,9 +638,8 @@ Returns additional information about the module in question in the form
}
```
During the build, this object represents currently available information about the module. Before the [`buildEnd`](guide/en/#buildend) hook, this information may be incomplete as e.g.
the `importedIds` are not yet resolved or additional `importers` are discovered.
During the build, this object represents currently available information about the module. Before the [`buildEnd`](guide/en/#buildend) hook, this information may be incomplete as e.g. the `importedIds` are not yet resolved or additional `importers` are discovered.
Returns `null` if the module id cannot be found.
#### `this.getWatchFiles() => string[]`
@ -696,9 +660,10 @@ An object containing potentially useful Rollup metadata:
Use Rollup's internal acorn instance to parse code to an AST.
#### `this.resolve(source: string, importer?: string, options?: {skipSelf?: boolean, custom?: {[plugin: string]: any}}) => Promise<{id: string, external: boolean | "absolute", moduleSideEffects: boolean | 'no-treeshake', syntheticNamedExports: boolean | string, meta: {[plugin: string]: any}} | null>`
Resolve imports to module ids (i.e. file names) using the same plugins that Rollup uses, and determine if an import should be external. If `null` is returned, the import could not be resolved by Rollup or any plugin but was not explicitly marked as external by the user. If an absolute external id is returned that should remain absolute in the output either via the [`makeAbsoluteExternalsRelative`](guide/en/#makeabsoluteexternalsrelative) option or by explicit plugin choice in the [`resolveId`](guide/en/#resolveid) hook, `external` will be `"absolute"` instead of `true`.
If you pass `skipSelf: true`, then the `resolveId` hook of the plugin from which `this.resolve` is called will be skipped when resolving. When other plugins themselves also call `this.resolve` in their `resolveId` hooks with the *exact same `source` and `importer`* while handling the original `this.resolve` call, then the `resolveId` hook of the original plugin will be skipped for those calls as well. The rationale here is that the plugin already stated that it "does not know" how to resolve this particular combination of `source` and `importer` at this point in time. If you do not want this behaviour, do not use `skipSelf` but implement your own infinite loop prevention mechanism if necessary.
If you pass `skipSelf: true`, then the `resolveId` hook of the plugin from which `this.resolve` is called will be skipped when resolving. When other plugins themselves also call `this.resolve` in their `resolveId` hooks with the _exact same `source` and `importer`_ while handling the original `this.resolve` call, then the `resolveId` hook of the original plugin will be skipped for those calls as well. The rationale here is that the plugin already stated that it "does not know" how to resolve this particular combination of `source` and `importer` at this point in time. If you do not want this behaviour, do not use `skipSelf` but implement your own infinite loop prevention mechanism if necessary.
You can also pass an object of plugin-specific options via the `custom` option, see [custom resolver options](guide/en/#custom-resolver-options) for details.
@ -713,7 +678,7 @@ Using this method will queue warnings for a build. These warnings will be printe
The `warning` argument can be a `string` or an object with (at minimum) a `message` property:
```js
this.warn( 'hmm...' );
this.warn('hmm...');
// is equivalent to
this.warn({ message: 'hmm...' });
```
@ -747,12 +712,13 @@ The `position` argument is a character index where the warning was raised. If pr
- `this.moduleIds: IterableIterator<string>` - _**Use [`this.getModuleIds`](guide/en/#thisgetmoduleids--iterableiteratorstring)**_ - An `Iterator` that gives access to all module ids in the current graph. It can be iterated via
```js
for (const moduleId of this.moduleIds) { /* ... */ }
for (const moduleId of this.moduleIds) {
/* ... */
}
```
or converted into an Array via `Array.from(this.moduleIds)`.
- `this.resolveId(source: string, importer?: string) => Promise<string | null>` - _**Use [`this.resolve`](guide/en/#thisresolvesource-string-importer-string-options-skipself-boolean-custom-plugin-string-any--promiseid-string-external-boolean--absolute-modulesideeffects-boolean--no-treeshake-syntheticnamedexports-boolean--string-meta-plugin-string-any--null)**_ - Resolve imports to module ids (i.e. file names) using the same plugins that Rollup uses. Returns `null` if an id cannot be resolved.
### File URLs
@ -763,8 +729,8 @@ The following example will detect imports of `.svg` files, emit the imported fil
```js
// plugin
export default function svgResolverPlugin () {
return ({
export default function svgResolverPlugin() {
return {
resolveId(source, importer) {
if (source.endsWith('.svg')) {
return path.resolve(path.dirname(importer), source);
@ -772,7 +738,7 @@ export default function svgResolverPlugin () {
},
load(id) {
if (id.endsWith('.svg')) {
const referenceId = this.emitFile({
const referenceId = this.emitFile({
type: 'asset',
name: path.basename(id),
source: fs.readFileSync(id)
@ -780,7 +746,7 @@ export default function svgResolverPlugin () {
return `export default import.meta.ROLLUP_FILE_URL_${referenceId};`;
}
}
});
};
}
```
@ -800,8 +766,8 @@ The following example will detect imports prefixed with `register-paint-worklet:
```js
// plugin
const REGISTER_WORKLET = 'register-paint-worklet:';
export default function paintWorkletPlugin () {
return ({
export default function paintWorkletPlugin() {
return {
load(id) {
if (id.startsWith(REGISTER_WORKLET)) {
return `CSS.paintWorklet.addModule(import.meta.ROLLUP_FILE_URL_${this.emitFile({
@ -813,14 +779,14 @@ export default function paintWorkletPlugin () {
resolveId(source, importer) {
// We remove the prefix, resolve everything to absolute ids and add the prefix again
// This makes sure that you can use relative imports to define worklets
if (source.startsWith(REGISTER_WORKLET)) {
return this.resolve(source.slice(REGISTER_WORKLET.length), importer).then(
resolvedId => REGISTER_WORKLET + resolvedId.id
);
}
return null;
if (source.startsWith(REGISTER_WORKLET)) {
return this.resolve(source.slice(REGISTER_WORKLET.length), importer).then(
resolvedId => REGISTER_WORKLET + resolvedId.id
);
}
return null;
}
});
};
}
```
@ -863,19 +829,17 @@ The `transform` hook, if returning an object, can also include an `ast` property
#### Example Transformer
(Use [@rollup/pluginutils](https://github.com/rollup/plugins/tree/master/packages/pluginutils) for
commonly needed functions, and to implement a transformer in the recommended
manner.)
(Use [@rollup/pluginutils](https://github.com/rollup/plugins/tree/master/packages/pluginutils) for commonly needed functions, and to implement a transformer in the recommended manner.)
```js
import { createFilter } from '@rollup/pluginutils';
export default function myPlugin ( options = {} ) {
const filter = createFilter( options.include, options.exclude );
export default function myPlugin(options = {}) {
const filter = createFilter(options.include, options.exclude);
return {
transform ( code, id ) {
if ( !filter( id ) ) return;
transform(code, id) {
if (!filter(id)) return;
// proceed with the transformation...
return {
@ -898,8 +862,7 @@ return {
};
```
If the transformation does not move code, you can preserve existing sourcemaps
by returning `null`:
If the transformation does not move code, you can preserve existing sourcemaps by returning `null`:
```js
return {
@ -908,10 +871,10 @@ return {
};
```
If you create a plugin that you think would be useful to others, please publish
it to NPM and add submit it to [github.com/rollup/awesome](https://github.com/rollup/awesome)!
If you create a plugin that you think would be useful to others, please publish it to NPM and add submit it to [github.com/rollup/awesome](https://github.com/rollup/awesome)!
### Synthetic named exports
It is possible to designate a fallback export for missing exports by setting the `syntheticNamedExports` option for a module in the [`resolveId`](guide/en/#resolveid), [`load`](guide/en/#load) or [`transform`](guide/en/#transform) hook. If a string value is used for `syntheticNamedExports`, this module will fallback the resolution of any missing named exports to properties of the named export of the given name:
**dep.js: (`{syntheticNamedExports: '__synthetic'}`)**
@ -927,7 +890,7 @@ export const __synthetic = {
**main.js:**
```js
import { foo, bar, baz, __synthetic } from './dep.js'
import { foo, bar, baz, __synthetic } from './dep.js';
// logs "explicit" as non-synthetic exports take precedence
console.log(foo);
@ -956,18 +919,17 @@ The problem here, however, is that this proxy id may or may not cause unintended
Custom resolver option offer a solution here by allowing to pass additional options for plugins when manually resolving a module. This happens without changing the id and thus without impairing the ability for other plugins to resolve the module correctly if the intended target plugin is not present.
```js
function requestingPlugin() {
return {
name: 'requesting',
async buildStart() {
const resolution = await this.resolve('foo', undefined, {
custom: {resolving: {specialResolution: true}}
custom: { resolving: { specialResolution: true } }
});
console.log(resolution.id); // "special"
}
}
};
}
function resolvingPlugin() {
@ -979,7 +941,7 @@ function resolvingPlugin() {
}
return null;
}
}
};
}
```
@ -995,10 +957,10 @@ function annotatingPlugin() {
name: 'annotating',
transform(code, id) {
if (thisModuleIsSpecial(code, id)) {
return {meta: {annotating: {special: true}}}
return { meta: { annotating: { special: true } } };
}
}
}
};
}
function readingPlugin() {
@ -1006,11 +968,12 @@ function readingPlugin() {
return {
name: 'reading',
buildEnd() {
const specialModules = Array.from(this.getModuleIds())
.filter(id => this.getModuleInfo(id).meta.annotating?.special);
const specialModules = Array.from(this.getModuleIds()).filter(
id => this.getModuleInfo(id).meta.annotating?.special
);
// do something with this list
}
}
};
}
```

@ -18,7 +18,7 @@ Rollup strives to implement the specification for ES modules, not necessarily th
There are two primary reasons:
1. Philosophically, it's because Rollup is essentially a [polyfill](https://en.wikipedia.org/wiki/Polyfill_(programming)) of sorts for native module loaders in both Node and browsers. In a browser, `import foo from 'foo'` won't work, because browsers don't use Node's resolution algorithm.
1. Philosophically, it's because Rollup is essentially a [polyfill](<https://en.wikipedia.org/wiki/Polyfill_(programming)>) of sorts for native module loaders in both Node and browsers. In a browser, `import foo from 'foo'` won't work, because browsers don't use Node's resolution algorithm.
2. On a practical level, it's just much easier to develop software if these concerns are neatly separated with a good API. Rollup's core is quite large, and everything that stops it getting larger is a good thing. Meanwhile, it's easier to fix bugs and add features. By keeping Rollup lean, the potential for technical debt is small.
@ -51,12 +51,14 @@ export default value;
```
This does not affect code execution order or behaviour, but it will speed up how your code is loaded and parsed. Without this optimization, a JavaScript engine needs to perform the following steps to run `main.js`:
1. Load and parse `main.js`. At the end, an import to `other-entry.js` will be discovered.
2. Load and parse `other-entry.js`. At the end, an import to `external` will be discovered.
3. Load and parse `external`.
4. Execute `main.js`.
With this optimization, a JavaScript engine will discover all transitive dependencies after parsing an entry module, avoiding the waterfall:
1. Load and parse `main.js`. At the end, imports to `other-entry.js` and `external` will be discovered.
2. Load and parse `other-entry.js` and `external`. The import of `external` from `other-entry.js` is already loaded and parsed.
3. Execute `main.js`.

@ -38,8 +38,7 @@ https://github.com/rollup/rollup/wiki/Troubleshooting#treating-module-as-externa
the-answer (imported by main.js)
```
The resulting `bundle.js` will still work in Node.js, because the `import` declaration gets turned into a CommonJS `require` statement, but `the-answer` does *not* get included in the bundle. For that, we need a plugin.
The resulting `bundle.js` will still work in Node.js, because the `import` declaration gets turned into a CommonJS `require` statement, but `the-answer` does _not_ get included in the bundle. For that, we need a plugin.
#### @rollup/plugin-node-resolve
@ -61,25 +60,23 @@ export default {
file: 'bundle.js',
format: 'cjs'
},
plugins: [ resolve() ]
plugins: [resolve()]
};
```
This time, when you `npm run build`, no warning is emitted — the bundle contains the imported module.
#### @rollup/plugin-commonjs
Some libraries expose ES modules that you can import as-is — `the-answer` is one such module. But at the moment, the majority of packages on NPM are exposed as CommonJS modules instead. Until that changes, we need to convert CommonJS to ES2015 before Rollup can process them.
The [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/master/packages/commonjs) plugin does exactly that.
Note that most of the times `@rollup/plugin-commonjs` should go *before* other plugins that transform your modules — this is to prevent other plugins from making changes that break the CommonJS detection. An exception for this rule is the Babel plugin, if you're using it then place it before the commonjs one.
Note that most of the times `@rollup/plugin-commonjs` should go _before_ other plugins that transform your modules — this is to prevent other plugins from making changes that break the CommonJS detection. An exception for this rule is the Babel plugin, if you're using it then place it before the commonjs one.
### Peer dependencies
Let's say that you're building a library that has a peer dependency, such as React or Lodash. If you set up externals as described above, your rollup will bundle *all* imports:
Let's say that you're building a library that has a peer dependency, such as React or Lodash. If you set up externals as described above, your rollup will bundle _all_ imports:
```js
import answer from 'the-answer';
@ -100,12 +97,14 @@ export default {
file: 'bundle.js',
format: 'cjs'
},
plugins: [resolve({
// pass custom options to the resolve plugin
customResolveOptions: {
moduleDirectory: 'node_modules'
}
})],
plugins: [
resolve({
// pass custom options to the resolve plugin
customResolveOptions: {
moduleDirectory: 'node_modules'
}
})
],
// indicate which modules should be treated as external
external: ['lodash']
};
@ -119,7 +118,7 @@ The `external` key accepts either an array of module names, or a function which
export default {
// ...
external: id => /lodash/.test(id)
}
};
```
You might use this form if you're using [babel-plugin-lodash](https://github.com/lodash/babel-plugin-lodash) to cherry-pick `lodash` modules. In this case, Babel will convert your import statements to look like this:
@ -130,7 +129,6 @@ import _merge from 'lodash/merge';
The array form of `external` does not handle wildcards, so this import will only be treated as external in the functional form.
### Babel
Many developers use [Babel](https://babeljs.io/) in their projects in order to use the latest JavaScript features that aren't yet supported by browsers and Node.js.
@ -154,10 +152,7 @@ export default {
file: 'bundle.js',
format: 'cjs'
},
plugins: [
resolve(),
babel({ babelHelpers: 'bundled' })
]
plugins: [resolve(), babel({ babelHelpers: 'bundled' })]
};
```
@ -165,19 +160,13 @@ Before Babel will actually compile your code, it needs to be configured. Create
```json
{
"presets": [
"@babel/env"
]
"presets": ["@babel/env"]
}
```
We're putting our `.babelrc.json` file in `src`, rather than the project root. This allows us to have a different `.babelrc.json` for things like tests, if we need that later See the [Babel documentation](https://babeljs.io/docs/en/config-files#project-wide-configuration) for more information on both project wide and file relative configuration.
We're putting our `.babelrc.json` file in `src`, rather than the project root. This allows us to have a different `.babelrc.json` for things like tests, if we need that later See the [Babel documentation](https://babeljs.io/docs/en/config-files#project-wide-configuration) for more information on both project wide and file relative configuration.
Now, before we run rollup, we need to install
[`babel-core`](https://babeljs.io/docs/en/babel-core)
and the
[`env`](https://babeljs.io/docs/en/babel-preset-env)
preset:
Now, before we run rollup, we need to install [`babel-core`](https://babeljs.io/docs/en/babel-core) and the [`env`](https://babeljs.io/docs/en/babel-preset-env) preset:
```
npm i -D @babel/core @babel/preset-env
@ -191,7 +180,7 @@ import answer from 'the-answer';
export default () => {
console.log(`the answer is ${answer}`);
}
};
```
Run Rollup with `npm run build`, and check the bundle:
@ -201,9 +190,9 @@ Run Rollup with `npm run build`, and check the bundle:
var index = 42;
var main = (function () {
var main = function () {
console.log('the answer is ' + index);
});
};
module.exports = main;
```
@ -220,19 +209,19 @@ const rollup = require('rollup');
const rollupTypescript = require('@rollup/plugin-typescript');
gulp.task('build', () => {
return rollup.rollup({
input: './src/main.ts',
plugins: [
rollupTypescript()
]
}).then(bundle => {
return bundle.write({
file: './dist/library.js',
format: 'umd',
name: 'library',
sourcemap: true
return rollup
.rollup({
input: './src/main.ts',
plugins: [rollupTypescript()]
})
.then(bundle => {
return bundle.write({
file: './dist/library.js',
format: 'umd',
name: 'library',
sourcemap: true
});
});
});
});
```
@ -246,9 +235,7 @@ const rollupTypescript = require('@rollup/plugin-typescript');
gulp.task('build', async function () {
const bundle = await rollup.rollup({
input: './src/main.ts',
plugins: [
rollupTypescript()
]
plugins: [rollupTypescript()]
});
await bundle.write({

@ -8,11 +8,11 @@ If you get stuck, please try discussing the issue on the [Rollup Discord](https:
You probably already know that '`eval` is evil', at least according to some people. But it's particularly harmful with Rollup, because of how it works unlike other module bundlers, which wrap each module in a function, Rollup puts all your code in the same scope.
That's more efficient, but it means that the shared scope is 'polluted' whenever you use `eval`, whereas with a different bundler, modules that *didn't* use eval would not be polluted. A minifier can't mangle variable names in polluted code, because it can't guarantee that the code to be evaluated doesn't reference those variable names.
That's more efficient, but it means that the shared scope is 'polluted' whenever you use `eval`, whereas with a different bundler, modules that _didn't_ use eval would not be polluted. A minifier can't mangle variable names in polluted code, because it can't guarantee that the code to be evaluated doesn't reference those variable names.
Furthermore, **it poses a security risk** in that a malicious module could access another module's private variables with `eval('SUPER_SEKRIT')`.
Luckily, unless you *really do* intend for the evaluated code to have access to local variables (in which case you're probably doing something wrong!), you can achieve the same effect in one of two ways:
Luckily, unless you _really do_ intend for the evaluated code to have access to local variables (in which case you're probably doing something wrong!), you can achieve the same effect in one of two ways:
#### eval2 = eval
@ -23,27 +23,25 @@ var eval2 = eval;
(function () {
var foo = 42;
eval('console.log("with eval:",foo)'); // logs 'with eval: 42'
eval('console.log("with eval:",foo)'); // logs 'with eval: 42'
eval2('console.log("with eval2:",foo)'); // throws ReferenceError
})();
```
#### `new Function`
Using the [Function constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function) generates a function from the supplied string. Again, it runs in the global scope. If you need to call the function repeatedly, this is much, *much* faster than using `eval`.
Using the [Function constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function) generates a function from the supplied string. Again, it runs in the global scope. If you need to call the function repeatedly, this is much, _much_ faster than using `eval`.
### Tree-shaking Doesn't Seem to be Working
Sometimes, you'll end up with code in your bundle that doesn't seem like it should be there. For example, if you import a utility from `lodash-es`, you might expect that you'll get the bare minimum of code necessary for that utility to work.
But Rollup has to be conservative about what code it removes in order to guarantee that the end result will run correctly. If an imported module appears to have *side-effects*, either on bits of the module that you're using or on the global environment, Rollup plays it safe and includes those side-effects.
But Rollup has to be conservative about what code it removes in order to guarantee that the end result will run correctly. If an imported module appears to have _side-effects_, either on bits of the module that you're using or on the global environment, Rollup plays it safe and includes those side-effects.
Because static analysis in a dynamic language like JavaScript is hard, there will occasionally be false positives. Lodash is a good example of a module that *looks* like it has lots of side-effects, even in places that it doesn't. You can often mitigate those false positives by importing submodules (e.g. `import map from 'lodash-es/map'` rather than `import { map } from 'lodash-es'`).
Because static analysis in a dynamic language like JavaScript is hard, there will occasionally be false positives. Lodash is a good example of a module that _looks_ like it has lots of side-effects, even in places that it doesn't. You can often mitigate those false positives by importing submodules (e.g. `import map from 'lodash-es/map'` rather than `import { map } from 'lodash-es'`).
Rollup's static analysis will improve over time, but it will never be perfect in all cases  that's just JavaScript.
### Error: "[name] is not exported by [module]"
Occasionally you will see an error message like this:
@ -54,24 +52,21 @@ Import declarations must have corresponding export declarations in the imported
This error frequently occurs with CommonJS modules converted by [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/master/packages/commonjs), which makes a reasonable attempt to generate named exports from the CommonJS code but won't always succeed, because the freewheeling nature of CommonJS is at odds with the rigorous approach we benefit from in JavaScript modules. It can be solved by using the [namedExports](https://github.com/rollup/plugins/tree/master/packages/commonjs#custom-named-exports) option, which allows you to manually fill in the information gaps.
### Error: "this is undefined"
In a JavaScript module, `this` is `undefined` at the top level (i.e., outside functions). Because of that, Rollup will rewrite any `this` references to `undefined` so that the resulting behaviour matches what will happen when modules are natively supported.
There are occasional valid reasons for `this` to mean something else. If you're getting errors in your bundle, you can use `options.context` and `options.moduleContext` to change this behaviour.
### Warning: "Sourcemap is likely to be incorrect"
You'll see this warning if you generate a sourcemap with your bundle (`sourcemap: true` or `sourcemap: 'inline'`) but you're using one or more plugins that transformed code without generating a sourcemap for the transformation.
Usually, a plugin will only omit the sourcemap if it (the plugin, not the bundle) was configured with `sourcemap: false` so all you need to do is change that. If the plugin doesn't generate a sourcemap, consider raising an issue with the plugin author.
### Warning: "Treating [module] as external dependency"
Rollup will only resolve *relative* module IDs by default. This means that an import statement like this…
Rollup will only resolve _relative_ module IDs by default. This means that an import statement like this…
```js
import moment from 'moment';
@ -85,11 +80,11 @@ export default {
entry: 'src/index.js',
dest: 'bundle.js',
format: 'cjs',
external: [ 'moment' ] // <-- suppresses the warning
external: ['moment'] // <-- suppresses the warning
};
```
If you *do* want to include the module in your bundle, you need to tell Rollup how to find it. In most cases, this is a question of using [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve).
If you _do_ want to include the module in your bundle, you need to tell Rollup how to find it. In most cases, this is a question of using [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve).
Some modules, like `events` or `util`, are built in to Node.js. If you want to include those (for example, so that your bundle runs in the browser), you may need to include [rollup-plugin-polyfill-node](https://github.com/snowpackjs/rollup-plugin-polyfill-node).
@ -97,7 +92,6 @@ Some modules, like `events` or `util`, are built in to Node.js. If you want to i
For large projects, you may run into an EMFILE error when running Rollup in watch mode on macOS. If you experience this, disabling FSEvents may eliminate the problem:
```js
// rollup.config.js
export default {

File diff suppressed because it is too large Load Diff

@ -0,0 +1,59 @@
flowchart TB
classDef hook-parallel fill:#ffb3b3,stroke:#000;
classDef hook-sequential fill:#ffd2b3,stroke:#000;
classDef hook-first fill:#fff2b3,stroke:#000;
classDef hook-sequential-sync fill:#ffd2b3,stroke:#f00;
buildend("buildEnd"):::hook-parallel
click buildend "/guide/en/#buildend" _parent
buildstart("buildStart"):::hook-parallel
click buildstart "/guide/en/#buildstart" _parent
load("load"):::hook-first
click load "/guide/en/#load" _parent
moduleparsed("moduleParsed"):::hook-parallel
click moduleparsed "/guide/en/#moduleparsed" _parent
options("options"):::hook-sequential
click options "/guide/en/#options" _parent
resolvedynamicimport("resolveDynamicImport"):::hook-first
click resolvedynamicimport "/guide/en/#resolvedynamicimport" _parent
resolveid("resolveId"):::hook-first
click resolveid "/guide/en/#resolveid" _parent
transform("transform"):::hook-sequential
click transform "/guide/en/#transform" _parent
watchchange("watchChange"):::hook-sequential-sync
click watchchange "/guide/en/#watchchange" _parent
closewatcher("closeWatcher"):::hook-sequential-sync
click closewatcher "/guide/en/#closewatcher" _parent
options
--> buildstart
--> |each entry|resolveid
.-> |external|buildend
resolveid
--> |non-external|load
--> transform
--> moduleparsed
.-> |no imports|buildend
moduleparsed
--> |"each import()"|resolvedynamicimport
--> |non-external|load
moduleparsed
--> |each import|resolveid
resolvedynamicimport
.-> |external|buildend
resolvedynamicimport
--> |unresolved|resolveid

@ -0,0 +1,17 @@
<div class="legend-grid">
<div style="grid-column: 1; grid-row: 1">
<span class="legend-rect" style="background: #ffb3b3"></span>parallel
</div>
<div style="grid-column: 1; grid-row: 2">
<span class="legend-rect" style="background: #ffd2b3"></span>sequential
</div>
<div style="grid-column: 1; grid-row: 3">
<span class="legend-rect" style="background: #fff2b3"></span>first
</div>
<div style="grid-column: 2; grid-row: 1">
<span class="legend-rect" style="border-color: #000"></span>async
</div>
<div style="grid-column: 2; grid-row: 2">
<span class="legend-rect" style="border-color: #f00"></span>sync
</div>
</div>

@ -0,0 +1,80 @@
flowchart TB
classDef default fill:#fff;
classDef hook-parallel fill:#ffb3b3,stroke:#000;
classDef hook-sequential fill:#ffd2b3,stroke:#000;
classDef hook-first fill:#fff2b3,stroke:#000;
classDef hook-sequential-sync fill:#ffd2b3,stroke:#f00;
classDef hook-first-sync fill:#fff2b3,stroke:#f00;
augmentchunkhash("augmentChunkHash"):::hook-sequential-sync
click augmentchunkhash "/guide/en/#augmentchunkhash" _parent
banner("banner"):::hook-parallel
click banner "/guide/en/#banner" _parent
closebundle("closeBundle"):::hook-parallel
click closebundle "/guide/en/#closebundle" _parent
footer("footer"):::hook-parallel
click footer "/guide/en/#footer" _parent
generatebundle("generateBundle"):::hook-sequential
click generatebundle "/guide/en/#generatebundle" _parent
intro("intro"):::hook-parallel
click intro "/guide/en/#intro" _parent
outputoptions("outputOptions"):::hook-sequential-sync
click outputoptions "/guide/en/#outputoptions" _parent
outro("outro"):::hook-parallel
click outro "/guide/en/#outro" _parent
renderchunk("renderChunk"):::hook-sequential
click renderchunk "/guide/en/#renderchunk" _parent
renderdynamicimport("renderDynamicImport"):::hook-first-sync
click renderdynamicimport "/guide/en/#renderdynamicimport" _parent
rendererror("renderError"):::hook-parallel
click rendererror "/guide/en/#rendererror" _parent
renderstart("renderStart"):::hook-parallel
click renderstart "/guide/en/#renderstart" _parent
resolvefileurl("resolveFileUrl"):::hook-first-sync
click resolvefileurl "/guide/en/#resolvefileurl" _parent
resolveimportmeta("resolveImportMeta"):::hook-first-sync
click resolveimportmeta "/guide/en/#resolveimportmeta" _parent
writebundle("writeBundle"):::hook-parallel
click writebundle "/guide/en/#writebundle" _parent
outputoptions
--> renderstart
--> banner & footer & intro & outro
--> beforerenderdynamicimport(( ))
--> beforeaugmentchunkhash(( ))
--> |each chunk|augmentchunkhash
--> renderchunk
.-> generatebundle
--> writebundle
.-> closebundle
beforerenderdynamicimport
--> |"each import()"|renderdynamicimport
--> beforeaugmentchunkhash
augmentchunkhash
--> |each import.meta.*|beforeimportmeta(( ))
--> |import.meta.url|resolvefileurl
.-> renderchunk
beforeimportmeta
--> |other|resolveimportmeta
.-> renderchunk
rendererror
.-> closebundle

164
package-lock.json generated

@ -1282,12 +1282,6 @@
"integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
"dev": true
},
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"dev": true
},
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@ -1386,12 +1380,6 @@
"integrity": "sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw==",
"dev": true
},
"entities": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
"dev": true
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -2097,12 +2085,6 @@
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true
},
"get-stdin": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
"dev": true
},
"get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@ -2311,12 +2293,6 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
@ -2702,12 +2678,6 @@
"minimist": "^1.2.0"
}
},
"jsonc-parser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==",
"dev": true
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@ -2733,15 +2703,6 @@
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
"dev": true
},
"linkify-it": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz",
"integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==",
"dev": true,
"requires": {
"uc.micro": "^1.0.1"
}
},
"lint-staged": {
"version": "10.5.4",
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.4.tgz",
@ -2903,18 +2864,6 @@
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
"dev": true
},
"lodash.differencewith": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz",
"integrity": "sha1-uvr7yRi1UVTheRdqALsK76rIVLc=",
"dev": true
},
"lodash.flatten": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
"dev": true
},
"lodash.flattendeep": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
@ -3078,87 +3027,6 @@
}
}
},
"markdown-it": {
"version": "12.0.4",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.4.tgz",
"integrity": "sha512-34RwOXZT8kyuOJy25oJNJoulO8L0bTHYWXcdZBYZqFnjIy3NgjeoM3FmPXIOFQ26/lSHYMr8oc62B6adxXcb3Q==",
"dev": true,
"requires": {
"argparse": "^2.0.1",
"entities": "~2.1.0",
"linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
}
}
},
"markdownlint": {
"version": "0.23.1",
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.23.1.tgz",
"integrity": "sha512-iOEwhDfNmq2IJlaA8mzEkHYUi/Hwoa6Ss+HO5jkwUR6wQ4quFr0WzSx+Z9rsWZKUaPbyirIdL1zGmJRkWawr4Q==",
"dev": true,
"requires": {
"markdown-it": "12.0.4"
}
},
"markdownlint-cli": {
"version": "0.27.1",
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.27.1.tgz",
"integrity": "sha512-p1VV6aSbGrDlpUWzHizAnSNEQAweVR3qUI/AIUubxW7BGPXziSXkIED+uRtSohUlRS/jmqp3Wi4es5j6fIrdeQ==",
"dev": true,
"requires": {
"commander": "~7.1.0",
"deep-extend": "~0.6.0",
"get-stdin": "~8.0.0",
"glob": "~7.1.6",
"ignore": "~5.1.8",
"js-yaml": "^4.0.0",
"jsonc-parser": "~3.0.0",
"lodash.differencewith": "~4.5.0",
"lodash.flatten": "~4.4.0",
"markdownlint": "~0.23.1",
"markdownlint-rule-helpers": "~0.14.0",
"minimatch": "~3.0.4",
"minimist": "~1.2.5",
"rc": "~1.2.8"
},
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"commander": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz",
"integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==",
"dev": true
},
"js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"requires": {
"argparse": "^2.0.1"
}
}
}
},
"markdownlint-rule-helpers": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.14.0.tgz",
"integrity": "sha512-vRTPqSU4JK8vVXmjICHSBhwXUvbfh/VJo+j7hvxqe15tLJyomv3FLgFdFgb8kpj0Fe8SsJa/TZUAXv7/sN+N7A==",
"dev": true
},
"matcher-collection": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/matcher-collection/-/matcher-collection-2.0.1.tgz",
@ -3169,12 +3037,6 @@
"minimatch": "^3.0.2"
}
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
"dev": true
},
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -4032,26 +3894,6 @@
"safe-buffer": "^5.1.0"
}
},
"rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"dev": true,
"requires": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
},
"dependencies": {
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true
}
}
},
"read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@ -4882,12 +4724,6 @@
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==",
"dev": true
},
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
"dev": true
},
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",

@ -16,9 +16,9 @@
"ci:test": "npm run build:cjs && npm run build:bootstrap && npm run test:all",
"ci:test:only": "npm run build:cjs && npm run build:bootstrap && npm run test:only",
"ci:coverage": "npm run build:cjs && npm run build:bootstrap && nyc --reporter lcovonly mocha",
"lint": "npx eslint . --fix --cache && npm run lint:markdown",
"lint:nofix": "npx eslint . && npm run lint:markdown",
"lint:markdown": "markdownlint --config markdownlint.json docs/**/*.md",
"lint": "eslint . --fix --cache && prettier --write \"**/*.md\"",
"lint:nofix": "eslint . && prettier --check \"**/*.md\"",
"lint:markdown": "prettier --write \"**/*.md\"",
"perf": "npm run build:cjs && node --expose-gc scripts/perf.js",
"perf:debug": "node --inspect-brk scripts/perf-debug.js",
"perf:init": "node scripts/perf-init.js",
@ -93,7 +93,6 @@
"lint-staged": "^10.5.4",
"locate-character": "^2.0.5",
"magic-string": "^0.25.7",
"markdownlint-cli": "^0.27.1",
"micromatch": "^4.0.4",
"mocha": "^8.4.0",
"nyc": "^15.1.0",

Loading…
Cancel
Save