diff --git a/src/rollup/index.ts b/src/rollup/index.ts index 1f8798e1604..4f0246b0f54 100644 --- a/src/rollup/index.ts +++ b/src/rollup/index.ts @@ -188,162 +188,152 @@ export default async function rollup(rawInputOptions: GenericConfigObject): Prom timeStart('BUILD', 1); - return graph.pluginDriver - .hookParallel('buildStart', [inputOptions]) - .then(() => - graph.build( - inputOptions.input as string | string[] | Record, - inputOptions.manualChunks, - inputOptions.inlineDynamicImports as boolean - ) - ) - .then( - chunks => graph.pluginDriver.hookParallel('buildEnd', []).then(() => chunks), - err => - graph.pluginDriver.hookParallel('buildEnd', [err]).then(() => { - throw err; - }) - ) - .then(chunks => { - timeEnd('BUILD', 1); - - // ensure we only do one optimization pass per build - let optimized = false; - - function getOutputOptions(rawOutputOptions: GenericConfigObject) { - return normalizeOutputOptions( - inputOptions as GenericConfigObject, - rawOutputOptions, - chunks.length > 1, - graph.pluginDriver - ); - } + let chunks: Chunk[]; + + try { + await graph.pluginDriver.hookParallel('buildStart', [inputOptions]); + chunks = await graph.build( + inputOptions.input as string | string[] | Record, + inputOptions.manualChunks, + inputOptions.inlineDynamicImports as boolean + ); + } catch (err) { + await graph.pluginDriver.hookParallel('buildEnd', [err]); + throw err; + } - async function generate( - outputOptions: OutputOptions, - isWrite: boolean - ): Promise { - timeStart('GENERATE', 1); - - const assetFileNames = outputOptions.assetFileNames || 'assets/[name]-[hash][extname]'; - const outputBundleWithPlaceholders: OutputBundleWithPlaceholders = Object.create(null); - let outputBundle; - const inputBase = commondir(getAbsoluteEntryModulePaths(chunks)); - graph.pluginDriver.startOutput(outputBundleWithPlaceholders, assetFileNames); - - try { - await graph.pluginDriver.hookParallel('renderStart', []); - const addons = await createAddons(graph, outputOptions); - for (const chunk of chunks) { - if (!inputOptions.preserveModules) chunk.generateInternalExports(outputOptions); - if (chunk.facadeModule && chunk.facadeModule.isEntryPoint) - chunk.exportMode = getExportMode(chunk, outputOptions); - } - for (const chunk of chunks) { - chunk.preRender(outputOptions, inputBase); - } - if (!optimized && inputOptions.experimentalOptimizeChunks) { - optimizeChunks( - chunks, - outputOptions, - inputOptions.chunkGroupingSize as number, - inputBase - ); - optimized = true; - } - assignChunkIds( - chunks, - inputOptions, - outputOptions, - inputBase, - addons, - outputBundleWithPlaceholders - ); - outputBundle = assignChunksToBundle(chunks, outputBundleWithPlaceholders); - - await Promise.all( - chunks.map(chunk => { - const outputChunk = outputBundleWithPlaceholders[chunk.id as string] as OutputChunk; - return chunk.render(outputOptions, addons, outputChunk).then(rendered => { - outputChunk.code = rendered.code; - outputChunk.map = rendered.map; - - return graph.pluginDriver.hookParallel('ongenerate', [ - { bundle: outputChunk, ...outputOptions }, - outputChunk - ]); - }); - }) - ); - } catch (error) { - await graph.pluginDriver.hookParallel('renderError', [error]); - throw error; - } - await graph.pluginDriver.hookSeq('generateBundle', [outputOptions, outputBundle, isWrite]); - graph.pluginDriver.finaliseAssets(); + await graph.pluginDriver.hookParallel('buildEnd', []); + + timeEnd('BUILD', 1); + + // ensure we only do one optimization pass per build + let optimized = false; + + function getOutputOptions(rawOutputOptions: GenericConfigObject) { + return normalizeOutputOptions( + inputOptions as GenericConfigObject, + rawOutputOptions, + chunks.length > 1, + graph.pluginDriver + ); + } - timeEnd('GENERATE', 1); - return outputBundle; + async function generate(outputOptions: OutputOptions, isWrite: boolean): Promise { + timeStart('GENERATE', 1); + + const assetFileNames = outputOptions.assetFileNames || 'assets/[name]-[hash][extname]'; + const outputBundleWithPlaceholders: OutputBundleWithPlaceholders = Object.create(null); + let outputBundle; + const inputBase = commondir(getAbsoluteEntryModulePaths(chunks)); + graph.pluginDriver.startOutput(outputBundleWithPlaceholders, assetFileNames); + + try { + await graph.pluginDriver.hookParallel('renderStart', []); + const addons = await createAddons(graph, outputOptions); + for (const chunk of chunks) { + if (!inputOptions.preserveModules) chunk.generateInternalExports(outputOptions); + if (chunk.facadeModule && chunk.facadeModule.isEntryPoint) + chunk.exportMode = getExportMode(chunk, outputOptions); + } + for (const chunk of chunks) { + chunk.preRender(outputOptions, inputBase); + } + if (!optimized && inputOptions.experimentalOptimizeChunks) { + optimizeChunks(chunks, outputOptions, inputOptions.chunkGroupingSize as number, inputBase); + optimized = true; } + assignChunkIds( + chunks, + inputOptions, + outputOptions, + inputBase, + addons, + outputBundleWithPlaceholders + ); + outputBundle = assignChunksToBundle(chunks, outputBundleWithPlaceholders); + + await Promise.all( + chunks.map(chunk => { + const outputChunk = outputBundleWithPlaceholders[chunk.id as string] as OutputChunk; + return chunk.render(outputOptions, addons, outputChunk).then(rendered => { + outputChunk.code = rendered.code; + outputChunk.map = rendered.map; + + return graph.pluginDriver.hookParallel('ongenerate', [ + { bundle: outputChunk, ...outputOptions }, + outputChunk + ]); + }); + }) + ); + } catch (error) { + await graph.pluginDriver.hookParallel('renderError', [error]); + throw error; + } + await graph.pluginDriver.hookSeq('generateBundle', [outputOptions, outputBundle, isWrite]); + graph.pluginDriver.finaliseAssets(); + + timeEnd('GENERATE', 1); + return outputBundle; + } - const cache = useCache ? graph.getCache() : undefined; - const result: RollupBuild = { - cache: cache as RollupCache, - generate: ((rawOutputOptions: GenericConfigObject) => { - const promise = generate(getOutputOptions(rawOutputOptions), false).then(result => - createOutput(result) - ); - Object.defineProperty(promise, 'code', throwAsyncGenerateError); - Object.defineProperty(promise, 'map', throwAsyncGenerateError); - return promise; - }) as any, - watchFiles: Object.keys(graph.watchFiles), - write: ((rawOutputOptions: GenericConfigObject) => { - const outputOptions = getOutputOptions(rawOutputOptions); - if (!outputOptions.dir && !outputOptions.file) { + const cache = useCache ? graph.getCache() : undefined; + const result: RollupBuild = { + cache: cache as RollupCache, + generate: ((rawOutputOptions: GenericConfigObject) => { + const promise = generate(getOutputOptions(rawOutputOptions), false).then(result => + createOutput(result) + ); + Object.defineProperty(promise, 'code', throwAsyncGenerateError); + Object.defineProperty(promise, 'map', throwAsyncGenerateError); + return promise; + }) as any, + watchFiles: Object.keys(graph.watchFiles), + write: ((rawOutputOptions: GenericConfigObject) => { + const outputOptions = getOutputOptions(rawOutputOptions); + if (!outputOptions.dir && !outputOptions.file) { + error({ + code: 'MISSING_OPTION', + message: 'You must specify "output.file" or "output.dir" for the build.' + }); + } + return generate(outputOptions, true).then(async bundle => { + let chunkCnt = 0; + for (const fileName of Object.keys(bundle)) { + const file = bundle[fileName]; + if ((file as OutputAsset).isAsset) continue; + chunkCnt++; + if (chunkCnt > 1) break; + } + if (chunkCnt > 1) { + if (outputOptions.sourcemapFile) error({ - code: 'MISSING_OPTION', - message: 'You must specify "output.file" or "output.dir" for the build.' + code: 'INVALID_OPTION', + message: '"output.sourcemapFile" is only supported for single-file builds.' }); - } - return generate(outputOptions, true).then(bundle => { - let chunkCnt = 0; - for (const fileName of Object.keys(bundle)) { - const file = bundle[fileName]; - if ((file as OutputAsset).isAsset) continue; - chunkCnt++; - if (chunkCnt > 1) break; - } - if (chunkCnt > 1) { - if (outputOptions.sourcemapFile) - error({ - code: 'INVALID_OPTION', - message: '"output.sourcemapFile" is only supported for single-file builds.' - }); - if (typeof outputOptions.file === 'string') - error({ - code: 'INVALID_OPTION', - message: - 'When building multiple chunks, the "output.dir" option must be used, not "output.file".' + - (typeof inputOptions.input !== 'string' || - inputOptions.inlineDynamicImports === true - ? '' - : ' To inline dynamic imports, set the "inlineDynamicImports" option.') - }); - } - return Promise.all( - Object.keys(bundle).map(chunkId => - writeOutputFile(graph, result, bundle[chunkId], outputOptions) - ) - ) - .then(() => graph.pluginDriver.hookParallel('writeBundle', [bundle])) - .then(() => createOutput(bundle)); - }); - }) as any - }; - if (inputOptions.perf === true) result.getTimings = getTimings; - return result; - }); + if (typeof outputOptions.file === 'string') + error({ + code: 'INVALID_OPTION', + message: + 'When building multiple chunks, the "output.dir" option must be used, not "output.file".' + + (typeof inputOptions.input !== 'string' || + inputOptions.inlineDynamicImports === true + ? '' + : ' To inline dynamic imports, set the "inlineDynamicImports" option.') + }); + } + await Promise.all( + Object.keys(bundle).map(chunkId => + writeOutputFile(graph, result, bundle[chunkId], outputOptions) + ) + ); + await graph.pluginDriver.hookParallel('writeBundle', [bundle]); + return createOutput(bundle); + }); + }) as any + }; + if (inputOptions.perf === true) result.getTimings = getTimings; + return result; } enum SortingFileType {