From 2e15e30891a9842683ba010a131d643e06717d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Wed, 12 Oct 2022 22:10:39 +0800 Subject: [PATCH 01/12] fix: nested plugin in options stage --- src/rollup/rollup.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rollup/rollup.ts b/src/rollup/rollup.ts index de060205b10..188f13c18ab 100644 --- a/src/rollup/rollup.ts +++ b/src/rollup/rollup.ts @@ -20,12 +20,14 @@ import { ANONYMOUS_OUTPUT_PLUGIN_PREFIX, ANONYMOUS_PLUGIN_PREFIX } from '../util import { getTimings, initialiseTimers, timeEnd, timeStart } from '../utils/timers'; import type { InputOptions, + InputPluginOption, NormalizedInputOptions, NormalizedOutputOptions, OutputAsset, OutputBundle, OutputChunk, OutputOptions, + OutputPluginOption, Plugin, RollupBuild, RollupOptions, From 347fb815c0268f53a5183bb286bfa158a921a6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 02:04:52 +0800 Subject: [PATCH 02/12] chore: remove unused --- src/rollup/rollup.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/rollup/rollup.ts b/src/rollup/rollup.ts index 188f13c18ab..de060205b10 100644 --- a/src/rollup/rollup.ts +++ b/src/rollup/rollup.ts @@ -20,14 +20,12 @@ import { ANONYMOUS_OUTPUT_PLUGIN_PREFIX, ANONYMOUS_PLUGIN_PREFIX } from '../util import { getTimings, initialiseTimers, timeEnd, timeStart } from '../utils/timers'; import type { InputOptions, - InputPluginOption, NormalizedInputOptions, NormalizedOutputOptions, OutputAsset, OutputBundle, OutputChunk, OutputOptions, - OutputPluginOption, Plugin, RollupBuild, RollupOptions, From 12bb3db344739563f881342ceb914a3ebd4f72c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 02:24:25 +0800 Subject: [PATCH 03/12] feat: support async plugins --- cli/run/commandPlugins.ts | 2 +- src/rollup/rollup.ts | 27 ++++++++++++--------- src/rollup/types.d.ts | 16 ++++++++++-- src/utils/asyncFlatten.ts | 6 +++++ src/utils/options/normalizeInputOptions.ts | 6 ++--- src/utils/options/normalizeOutputOptions.ts | 6 ++--- src/utils/options/options.ts | 8 +++--- 7 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 src/utils/asyncFlatten.ts diff --git a/cli/run/commandPlugins.ts b/cli/run/commandPlugins.ts index c59d82e9070..2076dd590b7 100644 --- a/cli/run/commandPlugins.ts +++ b/cli/run/commandPlugins.ts @@ -23,7 +23,7 @@ export async function addPluginsFromCommandOption( inputOptions: InputOptionsWithPlugins ): Promise { if (commandPlugin) { - const plugins: any[] = normalizePluginOption(commandPlugin as any); + const plugins = await normalizePluginOption(commandPlugin); for (const plugin of plugins) { if (/[={}]/.test(plugin)) { // -p plugin=value diff --git a/src/rollup/rollup.ts b/src/rollup/rollup.ts index de060205b10..39462be242e 100644 --- a/src/rollup/rollup.ts +++ b/src/rollup/rollup.ts @@ -111,9 +111,9 @@ async function getInputOptions( } const rawPlugins = getSortedValidatedPlugins( 'options', - normalizePluginOption(rawInputOptions.plugins) + await normalizePluginOption(rawInputOptions.plugins) ); - const { options, unsetOptions } = normalizeInputOptions( + const { options, unsetOptions } = await normalizeInputOptions( await rawPlugins.reduce(applyOptionHook(watchMode), Promise.resolve(rawInputOptions)) ); normalizePlugins(options.plugins, ANONYMOUS_PLUGIN_PREFIX); @@ -138,7 +138,7 @@ function normalizePlugins(plugins: readonly Plugin[], anonymousPrefix: string): } } -function handleGenerateWrite( +async function handleGenerateWrite( isWrite: boolean, inputOptions: NormalizedInputOptions, unsetInputOptions: ReadonlySet, @@ -149,7 +149,7 @@ function handleGenerateWrite( options: outputOptions, outputPluginDriver, unsetOptions - } = getOutputOptionsAndPluginDriver( + } = await getOutputOptionsAndPluginDriver( rawOutputOptions, graph.pluginDriver, inputOptions, @@ -175,35 +175,40 @@ function handleGenerateWrite( }); } -function getOutputOptionsAndPluginDriver( +async function getOutputOptionsAndPluginDriver( rawOutputOptions: OutputOptions, inputPluginDriver: PluginDriver, inputOptions: NormalizedInputOptions, unsetInputOptions: ReadonlySet -): { +): Promise<{ options: NormalizedOutputOptions; outputPluginDriver: PluginDriver; unsetOptions: Set; -} { +}> { if (!rawOutputOptions) { throw new Error('You must supply an options object'); } - const rawPlugins = normalizePluginOption(rawOutputOptions.plugins); + const rawPlugins = await normalizePluginOption(rawOutputOptions.plugins); normalizePlugins(rawPlugins, ANONYMOUS_OUTPUT_PLUGIN_PREFIX); const outputPluginDriver = inputPluginDriver.createOutputPluginDriver(rawPlugins); return { - ...getOutputOptions(inputOptions, unsetInputOptions, rawOutputOptions, outputPluginDriver), + ...(await getOutputOptions( + inputOptions, + unsetInputOptions, + rawOutputOptions, + outputPluginDriver + )), outputPluginDriver }; } -function getOutputOptions( +async function getOutputOptions( inputOptions: NormalizedInputOptions, unsetInputOptions: ReadonlySet, rawOutputOptions: OutputOptions, outputPluginDriver: PluginDriver -): { options: NormalizedOutputOptions; unsetOptions: Set } { +): Promise<{ options: NormalizedOutputOptions; unsetOptions: Set }> { return normalizeOutputOptions( outputPluginDriver.hookReduceArg0Sync( 'outputOptions', diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 146c2db6e5a..033bb0fb9a7 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -495,7 +495,13 @@ export type SourcemapPathTransformOption = ( sourcemapPath: string ) => string; -export type InputPluginOption = Plugin | null | false | undefined | InputPluginOption[]; +export type InputPluginOption = + | Plugin + | null + | false + | undefined + | InputPluginOption[] + | Promise; export interface InputOptions { acorn?: Record; @@ -619,7 +625,13 @@ export type NormalizedAmdOptions = ( type AddonFunction = (chunk: RenderedChunk) => string | Promise; -type OutputPluginOption = OutputPlugin | null | false | undefined | OutputPluginOption[]; +type OutputPluginOption = + | OutputPlugin + | null + | false + | undefined + | OutputPluginOption[] + | Promise; export interface OutputOptions { amd?: AmdOptions; diff --git a/src/utils/asyncFlatten.ts b/src/utils/asyncFlatten.ts new file mode 100644 index 00000000000..06e58e3ed67 --- /dev/null +++ b/src/utils/asyncFlatten.ts @@ -0,0 +1,6 @@ +export async function asyncFlatten(array: T[]): Promise { + do { + array = (await Promise.all(array)).flat(Infinity) as any; + } while (array.some((v: any) => v?.then)); + return array; +} diff --git a/src/utils/options/normalizeInputOptions.ts b/src/utils/options/normalizeInputOptions.ts index 114c5ea3cdf..d28675db19d 100644 --- a/src/utils/options/normalizeInputOptions.ts +++ b/src/utils/options/normalizeInputOptions.ts @@ -26,10 +26,10 @@ export interface CommandConfigObject { globals: { [id: string]: string } | undefined; } -export function normalizeInputOptions(config: InputOptions): { +export async function normalizeInputOptions(config: InputOptions): Promise<{ options: NormalizedInputOptions; unsetOptions: Set; -} { +}> { // These are options that may trigger special warnings or behaviour later // if the user did not select an explicit value const unsetOptions = new Set(); @@ -54,7 +54,7 @@ export function normalizeInputOptions(config: InputOptions): { moduleContext: getModuleContext(config, context), onwarn, perf: config.perf || false, - plugins: normalizePluginOption(config.plugins), + plugins: await normalizePluginOption(config.plugins), preserveEntrySignatures: config.preserveEntrySignatures ?? 'exports-only', preserveModules: getPreserveModules(config, onwarn, strictDeprecations), preserveSymlinks: config.preserveSymlinks || false, diff --git a/src/utils/options/normalizeOutputOptions.ts b/src/utils/options/normalizeOutputOptions.ts index c0904bd8cd9..3e0797e9908 100644 --- a/src/utils/options/normalizeOutputOptions.ts +++ b/src/utils/options/normalizeOutputOptions.ts @@ -22,11 +22,11 @@ import { warnUnknownOptions } from './options'; -export function normalizeOutputOptions( +export async function normalizeOutputOptions( config: OutputOptions, inputOptions: NormalizedInputOptions, unsetInputOptions: ReadonlySet -): { options: NormalizedOutputOptions; unsetOptions: Set } { +): Promise<{ options: NormalizedOutputOptions; unsetOptions: Set }> { // These are options that may trigger special warnings or behaviour later // if the user did not select an explicit value const unsetOptions = new Set(unsetInputOptions); @@ -72,7 +72,7 @@ export function normalizeOutputOptions( noConflict: config.noConflict || false, outro: getAddon(config, 'outro'), paths: config.paths || {}, - plugins: normalizePluginOption(config.plugins), + plugins: await normalizePluginOption(config.plugins), preferConst, preserveModules, preserveModulesRoot: getPreserveModulesRoot(config), diff --git a/src/utils/options/options.ts b/src/utils/options/options.ts index de2e986d28d..c85ef2dfd0c 100644 --- a/src/utils/options/options.ts +++ b/src/utils/options/options.ts @@ -10,6 +10,7 @@ import type { Plugin, WarningHandler } from '../../rollup/types'; +import { asyncFlatten } from '../asyncFlatten'; import { error, errorInvalidOption, errorUnknownOption } from '../error'; import { printQuotedStringList } from '../printStringList'; @@ -151,6 +152,7 @@ const getHashFromObjectOption = (optionName: string): string => optionName.split('.').join('').toLowerCase(); export const normalizePluginOption: { - (plugins: InputPluginOption): Plugin[]; - (plugins: OutputPluginOption): OutputPlugin[]; -} = (plugins: any) => [plugins].flat(Infinity).filter(Boolean); + (plugins: InputPluginOption): Promise; + (plugins: OutputPluginOption): Promise; + (plugins: unknown): Promise; +} = async (plugins: any) => (await asyncFlatten([plugins])).filter(Boolean); From 5a404a172c85eb4ef870eb879e94ee97fe1a0b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 02:44:50 +0800 Subject: [PATCH 04/12] fix: watch --- cli/run/loadConfigFile.ts | 2 +- cli/run/loadConfigFromCommand.ts | 2 +- cli/run/watch-cli.ts | 6 +++--- src/utils/options/mergeOptions.ts | 13 ++++++------- src/watch/watch-proxy.ts | 16 +++++++++------- src/watch/watch.ts | 13 ++++++------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cli/run/loadConfigFile.ts b/cli/run/loadConfigFile.ts index f134db0af2c..ac4940e8394 100644 --- a/cli/run/loadConfigFile.ts +++ b/cli/run/loadConfigFile.ts @@ -31,7 +31,7 @@ export async function loadConfigFile( try { const normalizedConfigs: MergedRollupOptions[] = []; for (const config of configs) { - const options = mergeOptions(config, commandOptions, warnings.add); + const options = await mergeOptions(config, commandOptions, warnings.add); await addCommandPluginsToInputOptions(options, commandOptions); normalizedConfigs.push(options); } diff --git a/cli/run/loadConfigFromCommand.ts b/cli/run/loadConfigFromCommand.ts index 73da0098cd2..6fd8298bf38 100644 --- a/cli/run/loadConfigFromCommand.ts +++ b/cli/run/loadConfigFromCommand.ts @@ -13,7 +13,7 @@ export default async function loadConfigFromCommand(command: Record): Promise { await loadConfigFromFileAndTrack(configFile); } else { const { options, warnings } = await loadConfigFromCommand(command); - start(options, warnings); + await start(options, warnings); } - function start(configs: MergedRollupOptions[], warnings: BatchWarnings): void { + async function start(configs: MergedRollupOptions[], warnings: BatchWarnings): Promise { try { - watcher = rollup.watch(configs as any); + watcher = await rollup.watch(configs as any); } catch (error: any) { return handleError(error); } diff --git a/src/utils/options/mergeOptions.ts b/src/utils/options/mergeOptions.ts index 32ce1c3cd1c..739623eff0a 100644 --- a/src/utils/options/mergeOptions.ts +++ b/src/utils/options/mergeOptions.ts @@ -1,7 +1,6 @@ import type { ExternalOption, InputOptions, - InputPluginOption, MergedRollupOptions, OutputOptions, OutputPluginOption, @@ -41,13 +40,13 @@ export const commandAliases: { [key: string]: string } = { const EMPTY_COMMAND_OPTIONS = { external: [], globals: undefined }; -export function mergeOptions( +export async function mergeOptions( config: RollupOptions, rawCommandOptions: GenericConfigObject = EMPTY_COMMAND_OPTIONS, defaultOnWarnHandler: WarningHandler = defaultOnWarn -): MergedRollupOptions { +): Promise { const command = getCommandOptions(rawCommandOptions); - const inputOptions = mergeInputOptions(config, command, defaultOnWarnHandler); + const inputOptions = await mergeInputOptions(config, command, defaultOnWarnHandler); const warn = inputOptions.onwarn as WarningHandler; if (command.output) { Object.assign(command, command.output); @@ -108,11 +107,11 @@ type CompleteInputOptions = { [K in U]: InputOptions[K]; }; -function mergeInputOptions( +async function mergeInputOptions( config: InputOptions, overrides: CommandConfigObject, defaultOnWarnHandler: WarningHandler -): InputOptions { +): Promise { const getOption = (name: keyof InputOptions): any => overrides[name] ?? config[name]; const inputOptions: CompleteInputOptions = { acorn: getOption('acorn'), @@ -133,7 +132,7 @@ function mergeInputOptions( moduleContext: getOption('moduleContext'), onwarn: getOnWarn(config, defaultOnWarnHandler), perf: getOption('perf'), - plugins: normalizePluginOption(config.plugins as InputPluginOption), + plugins: await normalizePluginOption(config.plugins), preserveEntrySignatures: getOption('preserveEntrySignatures'), preserveModules: getOption('preserveModules'), preserveSymlinks: getOption('preserveSymlinks'), diff --git a/src/watch/watch-proxy.ts b/src/watch/watch-proxy.ts index eafb0102632..c3e7db2d4e8 100644 --- a/src/watch/watch-proxy.ts +++ b/src/watch/watch-proxy.ts @@ -1,15 +1,17 @@ -import type { RollupWatcher } from '../rollup/types'; +import type { RollupOptions, RollupWatcher } from '../rollup/types'; import { ensureArray } from '../utils/ensureArray'; import { error, errorInvalidOption } from '../utils/error'; -import type { GenericConfigObject } from '../utils/options/options'; +import { mergeOptions } from '../utils/options/mergeOptions'; import { WatchEmitter } from './WatchEmitter'; import { loadFsEvents } from './fsevents-importer'; -export default function watch(configs: GenericConfigObject[] | GenericConfigObject): RollupWatcher { +export default async function watch( + configs: RollupOptions[] | RollupOptions +): Promise { const emitter = new WatchEmitter() as RollupWatcher; - const configArray = ensureArray(configs); - const watchConfigs = configArray.filter(config => config.watch !== false); - if (watchConfigs.length === 0) { + const optionsList = await Promise.all(ensureArray(configs).map(config => mergeOptions(config))); + const watchOptionsList = optionsList.filter(config => config.watch !== false); + if (watchOptionsList.length === 0) { return error( errorInvalidOption( 'watch', @@ -20,6 +22,6 @@ export default function watch(configs: GenericConfigObject[] | GenericConfigObje } loadFsEvents() .then(() => import('./watch')) - .then(({ Watcher }) => new Watcher(watchConfigs, emitter)); + .then(({ Watcher }) => new Watcher(watchOptionsList, emitter)); return emitter; } diff --git a/src/watch/watch.ts b/src/watch/watch.ts index efd868a418a..32c428d0920 100644 --- a/src/watch/watch.ts +++ b/src/watch/watch.ts @@ -11,7 +11,6 @@ import type { RollupWatcher, WatcherOptions } from '../rollup/types'; -import { mergeOptions } from '../utils/options/mergeOptions'; import type { GenericConfigObject } from '../utils/options/options'; import { FileWatcher } from './fileWatcher'; @@ -44,11 +43,11 @@ export class Watcher { private running = true; private readonly tasks: Task[]; - constructor(configs: readonly GenericConfigObject[], emitter: RollupWatcher) { + constructor(optionsList: readonly MergedRollupOptions[], emitter: RollupWatcher) { this.emitter = emitter; emitter.close = this.close.bind(this); - this.tasks = configs.map(config => new Task(this, config)); - for (const { watch } of configs) { + this.tasks = optionsList.map(options => new Task(this, options)); + for (const { watch } of optionsList) { if (watch && typeof (watch as WatcherOptions).buildDelay === 'number') { this.buildDelay = Math.max(this.buildDelay, (watch as WatcherOptions).buildDelay!); } @@ -148,11 +147,11 @@ export class Task { private watched = new Set(); private readonly watcher: Watcher; - constructor(watcher: Watcher, config: GenericConfigObject) { + constructor(watcher: Watcher, options: MergedRollupOptions) { this.watcher = watcher; + this.options = options; - this.skipWrite = Boolean(config.watch && (config.watch as GenericConfigObject).skipWrite); - this.options = mergeOptions(config); + this.skipWrite = Boolean(options.watch && (options.watch as GenericConfigObject).skipWrite); this.outputs = this.options.output; this.outputFiles = this.outputs.map(output => { if (output.file || output.dir) return resolve(output.file || output.dir!); From 2fce027254ad27fd7a26daf669978788ffbf37e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 02:52:57 +0800 Subject: [PATCH 05/12] fix: watch --- src/watch/watch-proxy.ts | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/watch/watch-proxy.ts b/src/watch/watch-proxy.ts index c3e7db2d4e8..5529f95b45c 100644 --- a/src/watch/watch-proxy.ts +++ b/src/watch/watch-proxy.ts @@ -5,23 +5,25 @@ import { mergeOptions } from '../utils/options/mergeOptions'; import { WatchEmitter } from './WatchEmitter'; import { loadFsEvents } from './fsevents-importer'; -export default async function watch( - configs: RollupOptions[] | RollupOptions -): Promise { +export default function watch(configs: RollupOptions[] | RollupOptions): RollupWatcher { const emitter = new WatchEmitter() as RollupWatcher; - const optionsList = await Promise.all(ensureArray(configs).map(config => mergeOptions(config))); - const watchOptionsList = optionsList.filter(config => config.watch !== false); - if (watchOptionsList.length === 0) { - return error( - errorInvalidOption( - 'watch', - 'watch', - 'there must be at least one config where "watch" is not set to "false"' - ) - ); - } - loadFsEvents() - .then(() => import('./watch')) - .then(({ Watcher }) => new Watcher(watchOptionsList, emitter)); + + (async () => { + const optionsList = await Promise.all(ensureArray(configs).map(config => mergeOptions(config))); + const watchOptionsList = optionsList.filter(config => config.watch !== false); + if (watchOptionsList.length === 0) { + return error( + errorInvalidOption( + 'watch', + 'watch', + 'there must be at least one config where "watch" is not set to "false"' + ) + ); + } + loadFsEvents() + .then(() => import('./watch')) + .then(({ Watcher }) => new Watcher(watchOptionsList, emitter)); + })(); + return emitter; } From 60615161a1340a076a5df23febf6a708f65eea40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 02:54:47 +0800 Subject: [PATCH 06/12] fix: dts --- src/rollup/types.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 033bb0fb9a7..27f1d897b10 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -501,7 +501,7 @@ export type InputPluginOption = | false | undefined | InputPluginOption[] - | Promise; + | Promise; export interface InputOptions { acorn?: Record; From ec38dcca074982d47cf361ac1ee39beeacd7cbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 03:05:14 +0800 Subject: [PATCH 07/12] fix: await --- src/utils/options/mergeOptions.ts | 13 +++++++------ src/watch/watch.ts | 7 +++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/utils/options/mergeOptions.ts b/src/utils/options/mergeOptions.ts index 739623eff0a..5071374422d 100644 --- a/src/utils/options/mergeOptions.ts +++ b/src/utils/options/mergeOptions.ts @@ -3,7 +3,6 @@ import type { InputOptions, MergedRollupOptions, OutputOptions, - OutputPluginOption, RollupCache, RollupOptions, WarningHandler, @@ -53,8 +52,10 @@ export async function mergeOptions( } const outputOptionsArray = ensureArray(config.output); if (outputOptionsArray.length === 0) outputOptionsArray.push({}); - const outputOptions = outputOptionsArray.map(singleOutputOptions => - mergeOutputOptions(singleOutputOptions, command, warn) + const outputOptions = await Promise.all( + outputOptionsArray.map(singleOutputOptions => + mergeOutputOptions(singleOutputOptions, command, warn) + ) ); warnUnknownOptions( @@ -217,11 +218,11 @@ type CompleteOutputOptions = { [K in U]: OutputOptions[K]; }; -function mergeOutputOptions( +async function mergeOutputOptions( config: OutputOptions, overrides: OutputOptions, warn: WarningHandler -): OutputOptions { +): Promise { const getOption = (name: keyof OutputOptions): any => overrides[name] ?? config[name]; const outputOptions: CompleteOutputOptions = { amd: getObjectOption(config, overrides, 'amd'), @@ -261,7 +262,7 @@ function mergeOutputOptions( noConflict: getOption('noConflict'), outro: getOption('outro'), paths: getOption('paths'), - plugins: normalizePluginOption(config.plugins as OutputPluginOption), + plugins: await normalizePluginOption(config.plugins), preferConst: getOption('preferConst'), preserveModules: getOption('preserveModules'), preserveModulesRoot: getOption('preserveModulesRoot'), diff --git a/src/watch/watch.ts b/src/watch/watch.ts index 32c428d0920..5179082f8e1 100644 --- a/src/watch/watch.ts +++ b/src/watch/watch.ts @@ -11,7 +11,6 @@ import type { RollupWatcher, WatcherOptions } from '../rollup/types'; -import type { GenericConfigObject } from '../utils/options/options'; import { FileWatcher } from './fileWatcher'; const eventsRewrites: Record> = { @@ -48,8 +47,8 @@ export class Watcher { emitter.close = this.close.bind(this); this.tasks = optionsList.map(options => new Task(this, options)); for (const { watch } of optionsList) { - if (watch && typeof (watch as WatcherOptions).buildDelay === 'number') { - this.buildDelay = Math.max(this.buildDelay, (watch as WatcherOptions).buildDelay!); + if (watch && typeof watch.buildDelay === 'number') { + this.buildDelay = Math.max(this.buildDelay, watch.buildDelay!); } } process.nextTick(() => this.run()); @@ -151,7 +150,7 @@ export class Task { this.watcher = watcher; this.options = options; - this.skipWrite = Boolean(options.watch && (options.watch as GenericConfigObject).skipWrite); + this.skipWrite = Boolean(options.watch && options.watch.skipWrite); this.outputs = this.options.output; this.outputFiles = this.outputs.map(output => { if (output.file || output.dir) return resolve(output.file || output.dir!); From a6be6fdfe1210c6a797b79af7e464070d1dfee63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 03:26:43 +0800 Subject: [PATCH 08/12] fix: watch cli --- cli/run/watch-cli.ts | 6 +----- src/watch/watch-proxy.ts | 11 +++++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/cli/run/watch-cli.ts b/cli/run/watch-cli.ts index 09465174882..edf3e5868bb 100644 --- a/cli/run/watch-cli.ts +++ b/cli/run/watch-cli.ts @@ -75,11 +75,7 @@ export async function watch(command: Record): Promise { } async function start(configs: MergedRollupOptions[], warnings: BatchWarnings): Promise { - try { - watcher = await rollup.watch(configs as any); - } catch (error: any) { - return handleError(error); - } + watcher = rollup.watch(configs as any); watcher.on('event', event => { switch (event.code) { diff --git a/src/watch/watch-proxy.ts b/src/watch/watch-proxy.ts index 5529f95b45c..e44e1966893 100644 --- a/src/watch/watch-proxy.ts +++ b/src/watch/watch-proxy.ts @@ -1,3 +1,4 @@ +import { handleError } from '../../cli/logging'; import type { RollupOptions, RollupWatcher } from '../rollup/types'; import { ensureArray } from '../utils/ensureArray'; import { error, errorInvalidOption } from '../utils/error'; @@ -20,10 +21,12 @@ export default function watch(configs: RollupOptions[] | RollupOptions): RollupW ) ); } - loadFsEvents() - .then(() => import('./watch')) - .then(({ Watcher }) => new Watcher(watchOptionsList, emitter)); - })(); + await loadFsEvents(); + const { Watcher } = await import('./watch'); + new Watcher(watchOptionsList, emitter); + })().catch(error => { + handleError(error); + }); return emitter; } From 65d49f1826ead05a7a8f538c53eaff865dac94a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 04:30:41 +0800 Subject: [PATCH 09/12] test: add --- .../{nested-plugin => nested-and-async-plugin}/_config.js | 8 ++++---- .../{nested-plugin => nested-and-async-plugin}/main.js | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename test/function/samples/{nested-plugin => nested-and-async-plugin}/_config.js (72%) rename test/function/samples/{nested-plugin => nested-and-async-plugin}/main.js (100%) diff --git a/test/function/samples/nested-plugin/_config.js b/test/function/samples/nested-and-async-plugin/_config.js similarity index 72% rename from test/function/samples/nested-plugin/_config.js rename to test/function/samples/nested-and-async-plugin/_config.js index 60be2ce1083..414bab3cf72 100644 --- a/test/function/samples/nested-plugin/_config.js +++ b/test/function/samples/nested-and-async-plugin/_config.js @@ -8,17 +8,17 @@ const pluginA = { } }; -const pluginB = { - name: 'nested-plugin-2', +const pluginB = Promise.resolve({ + name: 'async-plugin-2', transform(code) { return code.replace('answer = 41', 'answer = 42'); } -}; +}); module.exports = { description: 'works when nested plugin', options: { // eslint-disable-next-line no-sparse-arrays - plugins: [[pluginA], [undefined, [null]], ,] + plugins: [[Promise.resolve(pluginA)], [undefined, Promise.resolve([null])], ,] } }; diff --git a/test/function/samples/nested-plugin/main.js b/test/function/samples/nested-and-async-plugin/main.js similarity index 100% rename from test/function/samples/nested-plugin/main.js rename to test/function/samples/nested-and-async-plugin/main.js From 4eb3e36978350ddca7367bfda6deb8d8114ba04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 13:16:34 +0800 Subject: [PATCH 10/12] chore: improve types --- src/rollup/rollup.ts | 2 +- src/rollup/types.d.ts | 20 ++++++-------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/rollup/rollup.ts b/src/rollup/rollup.ts index 39462be242e..914f5d72548 100644 --- a/src/rollup/rollup.ts +++ b/src/rollup/rollup.ts @@ -203,7 +203,7 @@ async function getOutputOptionsAndPluginDriver( }; } -async function getOutputOptions( +function getOutputOptions( inputOptions: NormalizedInputOptions, unsetInputOptions: ReadonlySet, rawOutputOptions: OutputOptions, diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 27f1d897b10..0ebdc347db9 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -1,5 +1,9 @@ export const VERSION: string; +type FalsyValue = false | null | undefined; +type MaybeArray = T | T[]; +type MaybePromise = T | Promise; + export interface RollupError extends RollupLog { name?: string; stack?: string; @@ -495,13 +499,7 @@ export type SourcemapPathTransformOption = ( sourcemapPath: string ) => string; -export type InputPluginOption = - | Plugin - | null - | false - | undefined - | InputPluginOption[] - | Promise; +export type InputPluginOption = MaybePromise; export interface InputOptions { acorn?: Record; @@ -625,13 +623,7 @@ export type NormalizedAmdOptions = ( type AddonFunction = (chunk: RenderedChunk) => string | Promise; -type OutputPluginOption = - | OutputPlugin - | null - | false - | undefined - | OutputPluginOption[] - | Promise; +type OutputPluginOption = MaybePromise; export interface OutputOptions { amd?: AmdOptions; From 8e729c9a6b2e85b8d3098114ada7b3151130c44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 14 Oct 2022 13:18:03 +0800 Subject: [PATCH 11/12] refactor: remove iife --- src/watch/watch-proxy.ts | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/watch/watch-proxy.ts b/src/watch/watch-proxy.ts index e44e1966893..98d65616ac3 100644 --- a/src/watch/watch-proxy.ts +++ b/src/watch/watch-proxy.ts @@ -1,5 +1,5 @@ import { handleError } from '../../cli/logging'; -import type { RollupOptions, RollupWatcher } from '../rollup/types'; +import type { MaybeArray, RollupOptions, RollupWatcher } from '../rollup/types'; import { ensureArray } from '../utils/ensureArray'; import { error, errorInvalidOption } from '../utils/error'; import { mergeOptions } from '../utils/options/mergeOptions'; @@ -9,24 +9,26 @@ import { loadFsEvents } from './fsevents-importer'; export default function watch(configs: RollupOptions[] | RollupOptions): RollupWatcher { const emitter = new WatchEmitter() as RollupWatcher; - (async () => { - const optionsList = await Promise.all(ensureArray(configs).map(config => mergeOptions(config))); - const watchOptionsList = optionsList.filter(config => config.watch !== false); - if (watchOptionsList.length === 0) { - return error( - errorInvalidOption( - 'watch', - 'watch', - 'there must be at least one config where "watch" is not set to "false"' - ) - ); - } - await loadFsEvents(); - const { Watcher } = await import('./watch'); - new Watcher(watchOptionsList, emitter); - })().catch(error => { + watchInternal(configs, emitter).catch(error => { handleError(error); }); return emitter; } + +async function watchInternal(configs: MaybeArray, emitter: RollupWatcher) { + const optionsList = await Promise.all(ensureArray(configs).map(config => mergeOptions(config))); + const watchOptionsList = optionsList.filter(config => config.watch !== false); + if (watchOptionsList.length === 0) { + return error( + errorInvalidOption( + 'watch', + 'watch', + 'there must be at least one config where "watch" is not set to "false"' + ) + ); + } + await loadFsEvents(); + const { Watcher } = await import('./watch'); + new Watcher(watchOptionsList, emitter); +} From 304f750d2caddd072ef2ac3bb755fbab1a2c8287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Sat, 15 Oct 2022 04:51:35 +0800 Subject: [PATCH 12/12] docs: add --- docs/999-big-list-of-options.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/999-big-list-of-options.md b/docs/999-big-list-of-options.md index a3479ee4e8f..0eff6b40e3c 100755 --- a/docs/999-big-list-of-options.md +++ b/docs/999-big-list-of-options.md @@ -258,9 +258,9 @@ this.a.b.c = ... #### output.plugins -Type: `OutputPlugin | (OutputPlugin | OutputPlugin[] | void)[]` +Type: `MaybeArray>` -Adds a plugin just to this output. See [Using output plugins](guide/en/#using-output-plugins) for more information on how to use output-specific plugins and [Plugins](guide/en/#plugin-development) on how to write your own. For plugins imported from packages, remember to call the imported plugin function (i.e. `commonjs()`, not just `commonjs`). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins. Nested plugins will be flatten. +Adds a plugin just to this output. See [Using output plugins](guide/en/#using-output-plugins) for more information on how to use output-specific plugins and [Plugins](guide/en/#plugin-development) on how to write your own. For plugins imported from packages, remember to call the imported plugin function (i.e. `commonjs()`, not just `commonjs`). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins. Nested plugins will be flatten. Async plugin will be awaited and resolved. Not every plugin can be used here. `output.plugins` is limited to plugins that only use hooks that run during `bundle.generate()` or `bundle.write()`, i.e. after Rollup's main analysis is complete. If you are a plugin author, see [output generation hooks](guide/en/#output-generation-hooks) to find out which hooks can be used. @@ -288,9 +288,9 @@ export default { #### plugins -Type: `Plugin | (Plugin | Plugin[] | void)[]` +Type: `MaybeArray>` -See [Using plugins](guide/en/#using-plugins) for more information on how to use plugins and [Plugins](guide/en/#plugin-development) on how to write your own (try it out, it's not as difficult as it may sound and very much extends what you can do with Rollup). For plugins imported from packages, remember to call the imported plugin function (i.e. `commonjs()`, not just `commonjs`). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins. Nested plugins will be flatten. +See [Using plugins](guide/en/#using-plugins) for more information on how to use plugins and [Plugins](guide/en/#plugin-development) on how to write your own (try it out, it's not as difficult as it may sound and very much extends what you can do with Rollup). For plugins imported from packages, remember to call the imported plugin function (i.e. `commonjs()`, not just `commonjs`). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins. Nested plugins will be flatten. Async plugins will be awaited and resolved. ```js // rollup.config.js