diff --git a/docs/05-plugin-development.md b/docs/05-plugin-development.md
index 1b3a3b76bac..79dfb3bf024 100644
--- a/docs/05-plugin-development.md
+++ b/docs/05-plugin-development.md
@@ -319,11 +319,11 @@ Additionally, [`closeBundle`](guide/en/#closebundle) can be called as the very l
#### `augmentChunkHash`
-**Type:** `(chunkInfo: ChunkInfo) => string`
**Kind:** `sync, sequential`
**Previous Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
**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`
**Kind:** `sync, sequential`
**Previous Hook:** [`renderChunk`](guide/en/#renderchunk).
**Next Hook:** [`renderChunk`](guide/en/#renderchunk) if there are other chunks that still need to be processed, otherwise [`generateBundle`](guide/en/#generatebundle).
-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.
+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 `code` and `map` and using placeholders for hashes in file names.
-The following plugin will invalidate the hash of chunk `foo` with the timestamp of the last build:
+The following plugin will invalidate the hash of chunk `foo` with the current timestamp:
```js
function augmentWithDatePlugin() {
@@ -340,7 +340,7 @@ function augmentWithDatePlugin() {
#### `banner`
-**Type:** `string | (() => string)`
**Kind:** `async, parallel`
**Previous Hook:** [`renderStart`](guide/en/#renderstart)
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
+**Type:** `string | ((chunk: ChunkInfo) => string)`
**Kind:** `async, sequential`
**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` in the current chunk.
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression in the next chunk if there is another one, otherwise [`renderChunk`](guide/en/#renderchunk) for the first chunk.
Cf. [`output.banner/output.footer`](guide/en/#outputbanneroutputfooter).
@@ -354,13 +354,13 @@ If a plugin wants to retain resources across builds in watch mode, they can chec
#### `footer`
-**Type:** `string | (() => string)`
**Kind:** `async, parallel`
**Previous Hook:** [`renderStart`](guide/en/#renderstart)
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
+**Type:** `string | ((chunk: ChunkInfo) => string)`
**Kind:** `async, sequential`
**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` in the current chunk.
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression in the next chunk if there is another one, otherwise [`renderChunk`](guide/en/#renderchunk) for the first chunk.
Cf. [`output.banner/output.footer`](guide/en/#outputbanneroutputfooter).
#### `generateBundle`
-**Type:** `(options: OutputOptions, bundle: { [fileName: string]: AssetInfo | ChunkInfo }, isWrite: boolean) => void`
**Kind:** `async, sequential`
**Previous Hook:** [`renderChunk`](guide/en/#renderchunk) for each chunk.
**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`
**Kind:** `async, sequential`
**Previous Hook:** [`augmentChunkHash`](guide/en/#augmentchunkhash).
**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:
@@ -394,6 +394,7 @@ type ChunkInfo = {
code: string | null;
};
};
+ moduleIds: string[];
name: string;
referencedFiles: string[];
type: 'chunk';
@@ -404,7 +405,7 @@ You can prevent files from being emitted by deleting them from the bundle object
#### `intro`
-**Type:** `string | (() => string)`
**Kind:** `async, parallel`
**Previous Hook:** [`renderStart`](guide/en/#renderstart)
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
+**Type:** `string | ((chunk: ChunkInfo) => string)`
**Kind:** `async, sequential`
**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` in the current chunk.
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression in the next chunk if there is another one, otherwise [`renderChunk`](guide/en/#renderchunk) for the first chunk.
Cf. [`output.intro/output.outro`](guide/en/#outputintrooutputoutro).
@@ -416,19 +417,28 @@ Replaces or manipulates the output options object passed to `bundle.generate()`
#### `outro`
-**Type:** `string | (() => string)`
**Kind:** `async, parallel`
**Previous Hook:** [`renderStart`](guide/en/#renderstart)
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression.
+**Type:** `string | ((chunk: ChunkInfo) => string)`
**Kind:** `async, sequential`
**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` in the current chunk.
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression in the next chunk if there is another one, otherwise [`renderChunk`](guide/en/#renderchunk) for the first chunk.
Cf. [`output.intro/output.outro`](guide/en/#outputintrooutputoutro).
#### `renderChunk`
-**Type:** `(code: string, chunk: ChunkInfo, options: OutputOptions) => string | { code: string, map: SourceMap } | null`
**Kind:** `async, sequential`
**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`.
**Next Hook:** [`generateBundle`](guide/en/#generatebundle).
+**Type:** `(code: string, chunk: ChunkInfo, options: OutputOptions, meta: { chunks: {[id: string]: ChunkInfo} }) => string | { code: string, map: SourceMap } | null`
**Kind:** `async, sequential`
**Previous Hook:** [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro), [`outro`](guide/en/#outro) of the last chunk.
**Next Hook:** [`augmentChunkHash`](guide/en/#augmentchunkhash).
-Can be used to transform individual chunks. Called for each Rollup output chunk file. Returning `null` will apply no transformations.
+Can be used to transform individual chunks. Called for each Rollup output chunk file. Returning `null` will apply no transformations. If you change code in this hook and want to support source maps, you need to return a `map` describing your changes, see [the section on source code transformations](#source-code-transformations).
+
+`chunk` contains additional information about the chunk using the same `ChunkInfo` type as the [`generateBundle`](guide/en/#generatebundle) hook with the following differences:
+
+- `code` and `map` are not set. Instead, use the `code` parameter of this hook.
+- all referenced chunk file names that would contain hashes will contain hash placeholders instead. This includes `fileName`, `imports`, `importedBindings`, `dynamicImports` and `implicitlyLoadedBefore`. When you use such a placeholder file name or part of it in the code returned from this hook, Rollup will replace the placeholder with the actual hash before `generateBundle`, making sure the hash reflects the actual content of the final generated chunk including all referenced file hashes.
+
+`chunk` is mutable and changes applied in this hook will propagate to other plugins and to the generated bundle. That means if you add or remove imports or exports in this hook, you should update `imports`, `importedBindings` and/or `exports`.
+
+`meta.chunks` contains information about all the chunks Rollup is generating and gives you access to their `ChunkInfo`, again using placeholders for hashes. That means you can explore the entire chunk graph in this hook.
#### `renderDynamicImport`
-**Type:** `({format: string, moduleId: string, targetModuleId: string | null, customResolution: string | null}) => {left: string, right: string} | null`
**Kind:** `sync, first`
**Previous Hook:** [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro), [`outro`](guide/en/#outro).
**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`
**Kind:** `sync, first`
**Previous Hook:** [`renderStart`](guide/en/#renderstart) if this is the first chunk, otherwise [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro), [`outro`](guide/en/#outro) of the previous chunk.
**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` in the current chunk.
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.
@@ -488,27 +498,25 @@ Called when rollup encounters an error during `bundle.generate()` or `bundle.wri
#### `renderStart`
-**Type:** `(outputOptions: OutputOptions, inputOptions: InputOptions) => void`
**Kind:** `async, parallel`
**Previous Hook:** [`outputOptions`](guide/en/#outputoptions)
**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`
**Kind:** `async, parallel`
**Previous Hook:** [`outputOptions`](guide/en/#outputoptions)
**Next Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression in the first chunk.
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`
**Kind:** `sync, first`
**Previous Hook:** [`augmentChunkHash`](guide/en/#augmentchunkhash) for each chunk that would contain a hash in the file name.
**Next Hook:** [`renderChunk`](guide/en/#renderchunk) for each chunk.
+**Type:** `({chunkId: string, fileName: string, format: string, moduleId: string, referenceId: string, relativePath: string}) => string | null`
**Kind:** `sync, first`
**Previous Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression in the current chunk
**Next Hook:** [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro), [`outro`](guide/en/#outro) in parallel for the current 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.
For that, all formats except CommonJS and UMD assume that they run in a browser environment where `URL` and `document` are available. In case that fails or to generate more optimized code, this hook can be used to customize this behaviour. To do that, the following information is available:
-- `chunkId`: The id of the chunk this file is referenced from.
-- `fileName`: The path and file name of the emitted asset, relative to `output.dir` without a leading `./`.
+- `chunkId`: The id of the chunk this file is referenced from. If the chunk file name would contain a hash, this id will contain a placeholder instead. Rollup will replace this placeholder with the actual file name if it ends up in the generated code.
+- `fileName`: The path and file name of the emitted file, relative to `output.dir` without a leading `./`. Again if this is a chunk that would have a hash in its name, it will contain a placeholder instead.
- `format`: The rendered output format.
- `moduleId`: The id of the original module this file is referenced from. Useful for conditionally resolving certain assets differently.
- `referenceId`: The reference id of the file.
- `relativePath`: The path and file name of the emitted file, relative to the chunk the file is referenced from. This will path will contain no leading `./` but may contain a leading `../`.
-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.
-
The following plugin will always resolve all files relative to the current document:
```js
@@ -524,7 +532,7 @@ function resolveToDocumentPlugin() {
#### `resolveImportMeta`
-**Type:** `(property: string | null, {chunkId: string, moduleId: string, format: string}) => string | null`
**Kind:** `sync, first`
**Previous Hook:** [`augmentChunkHash`](guide/en/#augmentchunkhash) for each chunk that would contain a hash in the file name.
**Next Hook:** [`renderChunk`](guide/en/#renderchunk) for each chunk.
+**Type:** `(property: string | null, {chunkId: string, moduleId: string, format: string}) => string | null`
**Kind:** `sync, first`
**Previous Hook:** [`renderDynamicImport`](guide/en/#renderdynamicimport) for each dynamic import expression in the current chunk
**Next Hook:** [`banner`](guide/en/#banner), [`footer`](guide/en/#footer), [`intro`](guide/en/#intro), [`outro`](guide/en/#outro) in parallel for the current 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.
@@ -546,7 +554,7 @@ function importMetaUrlCurrentModulePlugin() {
}
```
-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.
+If the `chunkId` would contain a hash, it will contain a placeholder instead. If this placeholder ends up in the generated code, Rollup will replace it with the actual chunk hash.
#### `writeBundle`
@@ -597,7 +605,11 @@ In both cases, either a `name` or a `fileName` can be supplied. If a `fileName`
You can reference the URL of an emitted file in any code returned by a [`load`](guide/en/#load) or [`transform`](guide/en/#transform) plugin hook via `import.meta.ROLLUP_FILE_URL_referenceId`. See [File URLs](guide/en/#file-urls) for more details and an example.
-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/#thisgetfilename) to determine the file name as soon as it is available
+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/#thisgetfilename) to determine the file name as soon as it is available. If the file name is not set explicitly, then
+
+- asset file names are available starting with the [`renderStart`](guide/en/#renderstart) hook. For assets that are emitted later, the file name will be available immediately after emitting the asset.
+- chunk file names that do not contain a hash are available as soon as chunks are created after the `renderStart` hook.
+- if a chunk file name would contain a hash, using `getFileName` in any hook before [`generateBundle`](guide/en/#generatebundle) will return a name containing a placeholder instead of the actual name. If you use this file name or parts of it in a chunk you transform in [`renderChunk`](guide/en/#renderchunk), Rollup will replace the placeholder with the actual hash before `generateBundle`, making sure the hash reflects the actual content of the final generated chunk including all referenced file hashes.
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.
@@ -1081,7 +1093,9 @@ function transformCodePlugin(options = {}) {
#### Source Code Transformations
-If a plugin transforms source code, it should generate a sourcemap automatically, unless there's a specific `sourceMap: false` option. Rollup only cares about the `mappings` property (everything else is handled automatically). If it doesn't make sense to generate a sourcemap, (e.g. [rollup-plugin-string](https://github.com/TrySound/rollup-plugin-string)), return an empty sourcemap:
+If a plugin transforms source code, it should generate a sourcemap automatically, unless there's a specific `sourceMap: false` option. Rollup only cares about the `mappings` property (everything else is handled automatically). [magic-string](https://github.com/Rich-Harris/magic-string) provides a simple way to generate such a map for elementary transformations like adding or removing code snippets.
+
+If it doesn't make sense to generate a sourcemap, (e.g. [rollup-plugin-string](https://github.com/TrySound/rollup-plugin-string)), return an empty sourcemap:
```js
return {
diff --git a/docs/999-big-list-of-options.md b/docs/999-big-list-of-options.md
index 541dda9ad61..9684ac61c13 100755
--- a/docs/999-big-list-of-options.md
+++ b/docs/999-big-list-of-options.md
@@ -389,17 +389,24 @@ The pattern to use for naming custom emitted assets to include in the build outp
- `[extname]`: The file extension of the asset including a leading dot, e.g. `.css`.
- `[ext]`: The file extension without a leading dot, e.g. `css`.
-- `[hash]`: A hash based on the name and content of the asset.
+- `[hash]`: A hash based on the content of the asset. You can also set a specific hash length via e.g. `[hash:10]`.
- `[name]`: The file name of the asset excluding any extension.
Forward slashes `/` can be used to place files in sub-directories. When using a function, `assetInfo` is a reduced version of the one in [`generateBundle`](guide/en/#generatebundle) without the `fileName`. See also [`output.chunkFileNames`](guide/en/#outputchunkfilenames), [`output.entryFileNames`](guide/en/#outputentryfilenames).
#### output.banner/output.footer
-Type: `string | (() => string | Promise)`
CLI: `--banner`/`--footer `
+Type: `string | ((chunk: ChunkInfo) => string | Promise)`
CLI: `--banner`/`--footer `
A string to prepend/append to the bundle. You can also supply a function that returns a `Promise` that resolves to a `string` to generate it asynchronously (Note: `banner` and `footer` options will not break sourcemaps).
+If you supply a function, `chunk` contains additional information about the chunk using the same `ChunkInfo` type as the [`generateBundle`](guide/en/#generatebundle) hook with the following differences:
+
+- `code` and `map` are not set as the chunk has not been rendered yet.
+- all referenced chunk file names that would contain hashes will contain hash placeholders instead. This includes `fileName`, `imports`, `importedBindings`, `dynamicImports` and `implicitlyLoadedBefore`. When you use such a placeholder file name or part of it in the code returned from this option, Rollup will replace the placeholder with the actual hash before `generateBundle`, making sure the hash reflects the actual content of the final generated chunk including all referenced file hashes.
+
+`chunk` is mutable and changes applied in this hook will propagate to other plugins and to the generated bundle. That means if you add or remove imports or exports in this hook, you should update `imports`, `importedBindings` and/or `exports`.
+
```js
// rollup.config.js
export default {
@@ -421,10 +428,10 @@ Type: `string | ((chunkInfo: ChunkInfo) => string)`
CLI: `--chunkFileNames <
The pattern to use for naming shared chunks created when code-splitting, or a function that is called per chunk to return such a pattern. Patterns support the following placeholders:
- `[format]`: The rendering format defined in the output options, e.g. `es` or `cjs`.
-- `[hash]`: A hash based on the content of the chunk and the content of all its dependencies.
+- `[hash]`: A hash based only on the content of the final generated chunk, including transformations in [`renderChunk`](guide/en/#renderchunk) and any referenced file hashes. You can also set a specific hash length via e.g. `[hash:10]`.
- `[name]`: The name of the chunk. This can be explicitly set via the [`output.manualChunks`](guide/en/#outputmanualchunks) option or when the chunk is created by a plugin via [`this.emitFile`](guide/en/#thisemitfile). Otherwise, it will be derived from the chunk contents.
-Forward slashes `/` can be used to place files in sub-directories. When using a function, `chunkInfo` is a reduced version of the one in [`generateBundle`](guide/en/#generatebundle) without properties that depend on file names. See also [`output.assetFileNames`](guide/en/#outputassetfilenames), [`output.entryFileNames`](guide/en/#outputentryfilenames).
+Forward slashes `/` can be used to place files in sub-directories. When using a function, `chunkInfo` is a reduced version of the one in [`generateBundle`](guide/en/#generatebundle) without properties that depend on file names and no information about the rendered modules as rendering only happens after file names have been generated. You can however access a list of included `moduleIds`. See also [`output.assetFileNames`](guide/en/#outputassetfilenames), [`output.entryFileNames`](guide/en/#outputentryfilenames).
#### output.compact
@@ -439,10 +446,10 @@ Type: `string | ((chunkInfo: ChunkInfo) => string)`
CLI: `--entryFileNames <
The pattern to use for chunks created from entry points, or a function that is called per entry chunk to return such a pattern. Patterns support the following placeholders:
- `[format]`: The rendering format defined in the output options, e.g. `es` or `cjs`.
-- `[hash]`: A hash based on the content of the entry point and the content of all its dependencies.
+- `[hash]`: A hash based only on the content of the final generated entry chunk, including transformations in [`renderChunk`](guide/en/#renderchunk) and any referenced file hashes. You can also set a specific hash length via e.g. `[hash:10]`.
- `[name]`: The file name (without extension) of the entry point, unless the object form of input was used to define a different name.
-Forward slashes `/` can be used to place files in sub-directories. When using a function, `chunkInfo` is a reduced version of the one in [`generateBundle`](guide/en/#generatebundle) without properties that depend on file names. See also [`output.assetFileNames`](guide/en/#outputassetfilenames), [`output.chunkFileNames`](guide/en/#outputchunkfilenames).
+Forward slashes `/` can be used to place files in sub-directories. When using a function, `chunkInfo` is a reduced version of the one in [`generateBundle`](guide/en/#generatebundle) without properties that depend on file names and no information about the rendered modules as rendering only happens after file names have been generated. You can however access a list of included `moduleIds`. See also [`output.assetFileNames`](guide/en/#outputassetfilenames), [`output.chunkFileNames`](guide/en/#outputchunkfilenames).
This pattern will also be used when setting the [`output.preserveModules`](guide/en/#outputpreservemodules) option. Here a different set of placeholders is available, though:
@@ -809,7 +816,7 @@ There are some additional options that have an effect on the generated interop c
#### output.intro/output.outro
-Type: `string | (() => string | Promise)`
CLI: `--intro`/`--outro `
+Type: `string | ((chunk: ChunkInfo) => string | Promise)`
CLI: `--intro`/`--outro `
Similar to [`output.banner/output.footer`](guide/en/#outputbanneroutputfooter), except that the code goes _inside_ any format-specific wrapper.
diff --git a/docs/build-hooks.mmd b/docs/build-hooks.mmd
index f86760ed215..484a98c9187 100644
--- a/docs/build-hooks.mmd
+++ b/docs/build-hooks.mmd
@@ -1,4 +1,5 @@
flowchart TB
+ classDef default fill:transparent, color:#000;
classDef hook-parallel fill:#ffb3b3,stroke:#000;
classDef hook-sequential fill:#ffd2b3,stroke:#000;
classDef hook-first fill:#fff2b3,stroke:#000;
diff --git a/docs/output-generation-hooks.mmd b/docs/output-generation-hooks.mmd
index 989ea902170..eccecdc9550 100644
--- a/docs/output-generation-hooks.mmd
+++ b/docs/output-generation-hooks.mmd
@@ -1,5 +1,5 @@
flowchart TB
- classDef default fill:#fff;
+ classDef default fill:transparent, color:#000;
classDef hook-parallel fill:#ffb3b3,stroke:#000;
classDef hook-sequential fill:#ffd2b3,stroke:#000;
classDef hook-first fill:#fff2b3,stroke:#000;
@@ -9,25 +9,25 @@ flowchart TB
augmentchunkhash("augmentChunkHash"):::hook-sequential-sync
click augmentchunkhash "/guide/en/#augmentchunkhash" _parent
- banner("banner"):::hook-parallel
+ banner("banner"):::hook-sequential
click banner "/guide/en/#banner" _parent
closebundle("closeBundle"):::hook-parallel
click closebundle "/guide/en/#closebundle" _parent
- footer("footer"):::hook-parallel
+ footer("footer"):::hook-sequential
click footer "/guide/en/#footer" _parent
generatebundle("generateBundle"):::hook-sequential
click generatebundle "/guide/en/#generatebundle" _parent
- intro("intro"):::hook-parallel
+ intro("intro"):::hook-sequential
click intro "/guide/en/#intro" _parent
outputoptions("outputOptions"):::hook-sequential-sync
click outputoptions "/guide/en/#outputoptions" _parent
- outro("outro"):::hook-parallel
+ outro("outro"):::hook-sequential
click outro "/guide/en/#outro" _parent
renderchunk("renderChunk"):::hook-sequential
@@ -54,27 +54,47 @@ flowchart TB
outputoptions
--> renderstart
- --> banner & footer & intro & outro
- --> beforerenderdynamicimport(( ))
- --> beforeaugmentchunkhash(( ))
- --> |each chunk|augmentchunkhash
- --> renderchunk
- .-> generatebundle
- --> writebundle
- .-> closebundle
+ --> |each chunk|beforerenderdynamicimport
- beforerenderdynamicimport
- --> |"each import()"|renderdynamicimport
- --> beforeaugmentchunkhash
+ afteraddons
+ --> |each chunk|renderchunk
augmentchunkhash
- --> |each import.meta.*|beforeimportmeta(( ))
- --> |import.meta.url|resolvefileurl
- .-> renderchunk
+ --> generatebundle
+ --> writebundle
+ .-> closebundle
- beforeimportmeta
- --> |other|resolveimportmeta
- .-> renderchunk
+ subgraph generateChunks [" "]
+ direction TB
+ beforerenderdynamicimport(( ))
+ ---> beforeresolveimportmeta(( ))
+ ----> beforereaddons(( ))
+ --> banner & footer & intro & outro
+ --> afteraddons(( ))
+ .-> |next chunk|beforerenderdynamicimport
+
+ beforerenderdynamicimport
+ --> |"each import()"|renderdynamicimport
+ --> beforerenderdynamicimport
+
+ beforeresolveimportmeta
+ --> |each import.meta.*|beforeimportmeta(( ))
+ --> |import.meta.url|resolvefileurl
+ --> afterresolveimportmeta(( ))
+
+ beforeimportmeta
+ --> |other|resolveimportmeta
+ --> afterresolveimportmeta
+
+ afterresolveimportmeta
+ --> beforeresolveimportmeta
+ end
+
+ renderchunk
+ --> augmentchunkhash
+ .-> |next chunk|renderchunk
+
+ style generateChunks stroke-width:0px;
rendererror
.-> closebundle
diff --git a/package-lock.json b/package-lock.json
index 6d8392fef3c..0573072f21d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "rollup",
- "version": "2.77.0",
+ "version": "3.0.0-0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "rollup",
- "version": "2.77.0",
+ "version": "3.0.0-0",
"license": "MIT",
"bin": {
"rollup": "dist/bin/rollup"
diff --git a/package.json b/package.json
index 8926cc55358..069d66b3f68 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "rollup",
- "version": "2.77.0",
+ "version": "3.0.0-0",
"description": "Next-generation ES module bundler",
"main": "dist/rollup.js",
"module": "dist/es/rollup.js",
diff --git a/src/Bundle.ts b/src/Bundle.ts
index 99123386fcf..d7cc3822a86 100644
--- a/src/Bundle.ts
+++ b/src/Bundle.ts
@@ -1,5 +1,6 @@
import Chunk from './Chunk';
-import type ExternalModule from './ExternalModule';
+import ExternalChunk from './ExternalChunk';
+import ExternalModule from './ExternalModule';
import type Graph from './Graph';
import Module from './Module';
import type {
@@ -8,12 +9,9 @@ import type {
NormalizedOutputOptions,
OutputBundle,
OutputBundleWithPlaceholders,
- OutputChunk,
WarningHandler
} from './rollup/types';
-import { FILE_PLACEHOLDER } from './utils/FileEmitter';
import type { PluginDriver } from './utils/PluginDriver';
-import { type Addons, createAddons } from './utils/addons';
import { getChunkAssignments } from './utils/chunkAssignment';
import commondir from './utils/commondir';
import {
@@ -23,8 +21,10 @@ import {
error
} from './utils/error';
import { sortByExecutionOrder } from './utils/executionOrder';
-import { type GenerateCodeSnippets, getGenerateCodeSnippets } from './utils/generateCodeSnippets';
-import { basename, isAbsolute } from './utils/path';
+import { getGenerateCodeSnippets } from './utils/generateCodeSnippets';
+import { getHashPlaceholderGenerator, HashPlaceholderGenerator } from './utils/hashPlaceholders';
+import { isAbsolute } from './utils/path';
+import { renderChunks } from './utils/renderChunks';
import { timeEnd, timeStart } from './utils/timers';
export default class Bundle {
@@ -42,28 +42,36 @@ export default class Bundle {
async generate(isWrite: boolean): Promise {
timeStart('GENERATE', 1);
const outputBundle: OutputBundleWithPlaceholders = Object.create(null);
- this.pluginDriver.setOutputBundle(outputBundle, this.outputOptions, this.facadeChunkByModule);
+ this.pluginDriver.setOutputBundle(outputBundle, this.outputOptions);
+
+ // TODO Lukas rethink time measuring points
try {
await this.pluginDriver.hookParallel('renderStart', [this.outputOptions, this.inputOptions]);
timeStart('generate chunks', 2);
- const chunks = await this.generateChunks();
+ const getHashPlaceholder = getHashPlaceholderGenerator();
+ const chunks = await this.generateChunks(outputBundle, getHashPlaceholder);
if (chunks.length > 1) {
validateOptionsForMultiChunkOutput(this.outputOptions, this.inputOptions.onwarn);
}
- const inputBase = commondir(getAbsoluteEntryModulePaths(chunks));
+ this.pluginDriver.setChunkInformation(this.facadeChunkByModule);
+
timeEnd('generate chunks', 2);
- timeStart('render modules', 2);
+ timeStart('render chunks', 2);
- // We need to create addons before prerender because at the moment, there
- // can be no async code between prerender and render due to internal state
- const addons = await createAddons(this.outputOptions, this.pluginDriver);
- const snippets = getGenerateCodeSnippets(this.outputOptions);
- this.prerenderChunks(chunks, inputBase, snippets);
- timeEnd('render modules', 2);
+ for (const chunk of chunks) {
+ chunk.generateExports();
+ }
+ await renderChunks(
+ chunks,
+ outputBundle,
+ this.pluginDriver,
+ this.outputOptions,
+ this.inputOptions.onwarn
+ );
- await this.addFinalizedChunksToBundle(chunks, inputBase, addons, outputBundle, snippets);
+ timeEnd('render chunks', 2);
} catch (err: any) {
await this.pluginDriver.hookParallel('renderError', [err]);
throw err;
@@ -79,28 +87,6 @@ export default class Bundle {
return outputBundle as OutputBundle;
}
- private async addFinalizedChunksToBundle(
- chunks: readonly Chunk[],
- inputBase: string,
- addons: Addons,
- outputBundle: OutputBundleWithPlaceholders,
- snippets: GenerateCodeSnippets
- ): Promise {
- this.assignChunkIds(chunks, inputBase, addons, outputBundle);
- for (const chunk of chunks) {
- outputBundle[chunk.id!] = chunk.getChunkInfoWithFileNames() as OutputChunk;
- }
- await Promise.all(
- chunks.map(async chunk => {
- const outputChunk = outputBundle[chunk.id!] as OutputChunk;
- Object.assign(
- outputChunk,
- await chunk.render(this.outputOptions, addons, outputChunk, snippets)
- );
- })
- );
- }
-
private async addManualChunks(
manualChunks: Record
): Promise