diff --git a/docs/05-plugins.md b/docs/05-plugins.md index 4b4dde5cf09..a50cd3f0f4f 100644 --- a/docs/05-plugins.md +++ b/docs/05-plugins.md @@ -90,7 +90,7 @@ Cf. [`output.banner/output.footer`](guide/en#output-banner-output-footer). #### `generateBundle` Type: `(options: OutputOptions, bundle: { [fileName: string]: AssetInfo | ChunkInfo }, isWrite: boolean) => void | Promise` -Called at the end of `bundle.generate()` or `bundle.write()`. `bundle` provides the full list of files being written or generated along with their details: +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: ``` // AssetInfo @@ -176,6 +176,11 @@ Type: `(id: string) => void` Notifies a plugin whenever rollup has detected a change to a monitored file in `--watch` mode. +#### `writeBundle` +Type: `( bundle: { [fileName: string]: AssetInfo | ChunkInfo }) => void | Promise` + +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. + ### Deprecated ☢️ These hooks have been deprecated and may be removed in a future Rollup version. diff --git a/src/rollup/index.ts b/src/rollup/index.ts index 4637c04873b..b27c4dfbd66 100644 --- a/src/rollup/index.ts +++ b/src/rollup/index.ts @@ -319,7 +319,9 @@ export default function rollup(rawInputOptions: GenericConfigObject): Promise { return writeOutputFile(graph, result, bundle[chunkId], outputOptions); }) - ).then(() => createOutput(bundle)); + ) + .then(() => graph.pluginDriver.hookSeq('writeBundle', [bundle])) + .then(() => createOutput(bundle)); }); }) }; diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index deee26f937a..80575b9f25c 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -212,6 +212,7 @@ export interface Plugin { bundle: OutputBundle, isWrite: boolean ) => void | Promise; + writeBundle?: (this: PluginContext, bundle: OutputBundle) => void | Promise; intro?: AddonHook; load?: LoadHook; name: string; diff --git a/test/hooks/index.js b/test/hooks/index.js index 089356efb80..6b85bac1269 100644 --- a/test/hooks/index.js +++ b/test/hooks/index.js @@ -787,6 +787,7 @@ module.exports = input; }), { generateBundle(options, outputBundle, isWrite) { + assert.strictEqual(isWrite, false); const chunk = outputBundle['input.js']; // can detect that b has been tree-shaken this way @@ -802,9 +803,37 @@ module.exports = input; } ] }) - .then(bundle => { - return bundle.generate({ format: 'es' }); - }); + .then(bundle => bundle.generate({ format: 'es' })); + }); + + it('supports writeBundle hook', () => { + const file = path.join(__dirname, 'tmp/bundle.js'); + let bundle; + let callCount = 0; + return rollup + .rollup({ + input: 'input', + plugins: [ + loader({ + input: `export { a as default } from 'dep';`, + dep: `export var a = 1; export var b = 2;` + }), + { + generateBundle(options, outputBundle, isWrite) { + bundle = outputBundle; + assert.strictEqual(isWrite, true); + } + }, + { + writeBundle(outputBundle) { + assert.deepStrictEqual(outputBundle, bundle); + callCount++; + } + } + ] + }) + .then(bundle => bundle.write({ format: 'esm', file })) + .then(() => assert.strictEqual(callCount, 1)); }); it('supports this.cache for plugins', () => {