diff --git a/cli/run/watch.ts b/cli/run/watch.ts index 6d59fdb9133..8562f218a81 100644 --- a/cli/run/watch.ts +++ b/cli/run/watch.ts @@ -32,50 +32,46 @@ export default async function watch(command: any) { } if (configFile) { - if (configFile.startsWith('node:')) { - ({ options: configs, warnings } = await loadAndParseConfigFile(configFile, command)); - } else { - let reloadingConfig = false; - let aborted = false; - let configFileData: string | null = null; - - configWatcher = fs.watch(configFile, (event: string) => { - if (event === 'change') reloadConfigFile(); - }); - - await reloadConfigFile(); - - async function reloadConfigFile() { - try { - const newConfigFileData = fs.readFileSync(configFile!, 'utf-8'); - if (newConfigFileData === configFileData) { - return; - } - if (reloadingConfig) { - aborted = true; - return; - } - if (configFileData) { - stderr(`\nReloading updated config...`); - } - configFileData = newConfigFileData; - reloadingConfig = true; - ({ options: configs, warnings } = await loadAndParseConfigFile(configFile!, command)); - reloadingConfig = false; - if (aborted) { - aborted = false; - reloadConfigFile(); - } else { - if (watcher) { - watcher.close(); - } - start(configs); + let reloadingConfig = false; + let aborted = false; + let configFileData: string | null = null; + + configWatcher = fs.watch(configFile, (event: string) => { + if (event === 'change') reloadConfigFile(); + }); + + await reloadConfigFile(); + + async function reloadConfigFile() { + try { + const newConfigFileData = fs.readFileSync(configFile!, 'utf-8'); + if (newConfigFileData === configFileData) { + return; + } + if (reloadingConfig) { + aborted = true; + return; + } + if (configFileData) { + stderr(`\nReloading updated config...`); + } + configFileData = newConfigFileData; + reloadingConfig = true; + ({ options: configs, warnings } = await loadAndParseConfigFile(configFile!, command)); + reloadingConfig = false; + if (aborted) { + aborted = false; + reloadConfigFile(); + } else { + if (watcher) { + watcher.close(); } - } catch (err) { - configs = []; - reloadingConfig = false; - handleError(err, true); + start(configs); } + } catch (err) { + configs = []; + reloadingConfig = false; + handleError(err, true); } } } else { diff --git a/test/cli/samples/watch/bundle-error/_config.js b/test/cli/samples/watch/bundle-error/_config.js new file mode 100644 index 00000000000..18b65f1bfd0 --- /dev/null +++ b/test/cli/samples/watch/bundle-error/_config.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const path = require('path'); + +let mainFile; + +module.exports = { + description: 'recovers from errors during bundling', + command: 'rollup -cw', + before() { + mainFile = path.resolve(__dirname, 'main.js'); + fs.writeFileSync(mainFile, '<=>'); + }, + abortOnStderr(data) { + if (data.includes('Error: Unexpected token')) { + setTimeout(() => fs.writeFileSync(mainFile, 'export default 42;'), 50); + return false; + } + if (data.includes('created _actual')) { + return true; + } + }, +}; diff --git a/test/cli/samples/watch/bundle-error/_expected/main.js b/test/cli/samples/watch/bundle-error/_expected/main.js new file mode 100644 index 00000000000..d862de816a3 --- /dev/null +++ b/test/cli/samples/watch/bundle-error/_expected/main.js @@ -0,0 +1,3 @@ +var main = 42; + +export default main; diff --git a/test/cli/samples/watch/bundle-error/main.js b/test/cli/samples/watch/bundle-error/main.js new file mode 100644 index 00000000000..a4012bff06c --- /dev/null +++ b/test/cli/samples/watch/bundle-error/main.js @@ -0,0 +1 @@ +export default 42; \ No newline at end of file diff --git a/test/cli/samples/watch/bundle-error/rollup.config.js b/test/cli/samples/watch/bundle-error/rollup.config.js new file mode 100644 index 00000000000..0c8c1cb886e --- /dev/null +++ b/test/cli/samples/watch/bundle-error/rollup.config.js @@ -0,0 +1,7 @@ +export default { + input: 'main.js', + output: { + dir: "_actual", + format: "es" + } +}; diff --git a/test/cli/samples/watch/no-config-file/_config.js b/test/cli/samples/watch/no-config-file/_config.js new file mode 100644 index 00000000000..f3f030d4806 --- /dev/null +++ b/test/cli/samples/watch/no-config-file/_config.js @@ -0,0 +1,9 @@ +module.exports = { + description: 'watches without a config file', + command: 'rollup main.js --watch --format es --file _actual/main.js', + abortOnStderr(data) { + if (data.includes('created _actual/main.js')) { + return true; + } + }, +}; diff --git a/test/cli/samples/watch/watch-config/_expected/output3.js b/test/cli/samples/watch/no-config-file/_expected/main.js similarity index 51% rename from test/cli/samples/watch/watch-config/_expected/output3.js rename to test/cli/samples/watch/no-config-file/_expected/main.js index 51a1fc49261..b72a22eac84 100644 --- a/test/cli/samples/watch/watch-config/_expected/output3.js +++ b/test/cli/samples/watch/no-config-file/_expected/main.js @@ -1,3 +1,3 @@ -const foo = 47; +const foo = 42; export { foo }; diff --git a/test/cli/samples/watch/no-config-file/main.js b/test/cli/samples/watch/no-config-file/main.js new file mode 100644 index 00000000000..9d7381d29f6 --- /dev/null +++ b/test/cli/samples/watch/no-config-file/main.js @@ -0,0 +1 @@ +export const foo = 42; diff --git a/test/cli/samples/watch/node-config-file/_config.js b/test/cli/samples/watch/node-config-file/_config.js new file mode 100644 index 00000000000..76205f3ea1b --- /dev/null +++ b/test/cli/samples/watch/node-config-file/_config.js @@ -0,0 +1,9 @@ +module.exports = { + description: 'watches using a node_modules config files', + command: 'rollup --watch --config node:custom', + abortOnStderr(data) { + if (data.includes('created _actual/main.js')) { + return true; + } + }, +}; diff --git a/test/cli/samples/watch/node-config-file/_expected/main.js b/test/cli/samples/watch/node-config-file/_expected/main.js new file mode 100644 index 00000000000..b72a22eac84 --- /dev/null +++ b/test/cli/samples/watch/node-config-file/_expected/main.js @@ -0,0 +1,3 @@ +const foo = 42; + +export { foo }; diff --git a/test/cli/samples/watch/node-config-file/main.js b/test/cli/samples/watch/node-config-file/main.js new file mode 100644 index 00000000000..9d7381d29f6 --- /dev/null +++ b/test/cli/samples/watch/node-config-file/main.js @@ -0,0 +1 @@ +export const foo = 42; diff --git a/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/index.js b/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/index.js new file mode 100644 index 00000000000..acb52c3147d --- /dev/null +++ b/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/index.js @@ -0,0 +1,7 @@ +module.exports = { + input: 'main.js', + output: { + file: '_actual/main.js', + format: 'es', + }, +}; diff --git a/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/package.json b/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/package.json new file mode 100644 index 00000000000..6b2fdf69cc5 --- /dev/null +++ b/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/package.json @@ -0,0 +1,5 @@ +{ + "name": "rollup-config-custom", + "version": "1.0.0", + "main": "index.js" +} diff --git a/test/cli/samples/watch/watch-config-early-update/_config.js b/test/cli/samples/watch/watch-config-early-update/_config.js new file mode 100644 index 00000000000..badd5165a8e --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/_config.js @@ -0,0 +1,73 @@ +const fs = require('fs'); +const path = require('path'); + +let configFile; +let messageFile; +let reloadTriggered = false; + +module.exports = { + description: 'immediately reloads the config file if a change happens while it is parsed', + command: 'rollup -cw', + before() { + configFile = path.resolve(__dirname, 'rollup.config.js'); + messageFile = path.resolve(__dirname, '_actual', 'message.txt'); + fs.mkdirSync(path.resolve(__dirname, '_actual')); + fs.writeFileSync(messageFile, 'initial'); + fs.writeFileSync( + configFile, + ` + import path from 'path'; + import fs from 'fs'; + const messageFile = path.resolve(__dirname, '_actual', 'message.txt'); + export default new Promise(resolve => { + fs.writeFileSync(messageFile, 'loading'); + const watcher = fs.watch(messageFile, event => { + if (event === 'change') { + const content = fs.readFileSync(messageFile, 'utf8'); + if (content === 'loaded') { + watcher.close(); + fs.writeFileSync(messageFile, 'resolved'); + resolve({ + input: {output1: "main.js"}, + output: { + dir: "_actual", + format: "es" + } + }); + } + } + }); + }); + ` + ); + const watcher = fs.watch(messageFile, (event) => { + if (event === 'change') { + const content = fs.readFileSync(messageFile, 'utf8'); + if (content === 'loading') { + watcher.close(); + fs.writeFileSync( + configFile, + ` + export default { + input: {output2: "main.js"}, + output: { + dir: "_actual", + format: "es" + } + }; + ` + ); + fs.writeFileSync(messageFile, 'loaded'); + } + } + }); + }, + abortOnStderr(data) { + if (reloadTriggered && data.includes('created _actual')) { + return true; + } else if (data.includes('Reloading updated config')) { + reloadTriggered = true; + return false; + } + }, +}; diff --git a/test/cli/samples/watch/watch-config-early-update/_expected/message.txt b/test/cli/samples/watch/watch-config-early-update/_expected/message.txt new file mode 100644 index 00000000000..5dd54033a94 --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/_expected/message.txt @@ -0,0 +1 @@ +resolved \ No newline at end of file diff --git a/test/cli/samples/watch/watch-config-early-update/_expected/output2.js b/test/cli/samples/watch/watch-config-early-update/_expected/output2.js new file mode 100644 index 00000000000..b72a22eac84 --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/_expected/output2.js @@ -0,0 +1,3 @@ +const foo = 42; + +export { foo }; diff --git a/test/cli/samples/watch/watch-config-early-update/main.js b/test/cli/samples/watch/watch-config-early-update/main.js new file mode 100644 index 00000000000..9d7381d29f6 --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/main.js @@ -0,0 +1 @@ +export const foo = 42; diff --git a/test/cli/samples/watch/watch-config-early-update/rollup.config.js b/test/cli/samples/watch/watch-config-early-update/rollup.config.js new file mode 100644 index 00000000000..ec6ec213bce --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/rollup.config.js @@ -0,0 +1,9 @@ + + export default { + input: {output2: "main.js"}, + output: { + dir: "_actual", + format: "es" + } + }; + \ No newline at end of file diff --git a/test/cli/samples/watch/watch-config/_config.js b/test/cli/samples/watch/watch-config/_config.js index ad10cccd7b3..199e01e8e73 100644 --- a/test/cli/samples/watch/watch-config/_config.js +++ b/test/cli/samples/watch/watch-config/_config.js @@ -4,6 +4,9 @@ const path = require('path'); let configFile; let currentlyBundling; +const updateConfigDelayed = (content) => + setTimeout(() => fs.writeFileSync(configFile, content), 50); + module.exports = { description: 'watches the config file', command: 'rollup -cw', @@ -17,8 +20,7 @@ module.exports = { return false; } if (data.includes('Config contains initial errors')) { - fs.writeFileSync( - configFile, + updateConfigDelayed( 'export default {\n' + '\tinput: "main1.js",\n' + '\toutput: {\n' + @@ -30,8 +32,7 @@ module.exports = { return false; } if (data.includes('Config contains further errors')) { - fs.writeFileSync( - configFile, + updateConfigDelayed( 'export default {\n' + '\tinput: ["main2.js", "main3.js"],\n' + '\toutput: {\n' + @@ -45,13 +46,12 @@ module.exports = { if (data.includes('created _actual')) { switch (currentlyBundling) { case 'main1.js': - fs.writeFileSync(configFile, 'throw new Error("Config contains further errors");'); + updateConfigDelayed('throw new Error("Config contains further errors");'); return false; case 'main2.js, main3.js': - fs.writeFileSync( - configFile, + updateConfigDelayed( 'export default {\n' + - '\tinput: {output1: "main4.js"},\n' + + '\tinput: {output: "main4.js"},\n' + '\toutput: {\n' + '\t\tdir: "_actual",\n' + '\t\tformat: "es"\n' + @@ -60,43 +60,8 @@ module.exports = { ); return false; case 'main4.js': - currentlyBundling = 'preparing main5.js'; - fs.writeFileSync( - configFile, - 'export default {\n' + - '\tinput: {output2: "main5.js"},\n' + - '\toutput: {\n' + - '\t\tdir: "_actual",\n' + - '\t\tformat: "es"\n' + - '\t}\n' + - '};' - ); - return false; - case 'main6.js': - fs.writeFileSync( - configFile, - 'export default {\n' + - '\tinput: {output3: "main6.js"},\n' + - '\toutput: {\n' + - '\t\tdir: "_actual",\n' + - '\t\tformat: "es"\n' + - '\t}\n' + - '};' - ); return true; } } - if (data.includes('Reloading updated config') && currentlyBundling === 'preparing main5.js') { - fs.writeFileSync( - configFile, - 'export default {\n' + - '\tinput: {output3: "main6.js"},\n' + - '\toutput: {\n' + - '\t\tdir: "_actual",\n' + - '\t\tformat: "es"\n' + - '\t}\n' + - '};' - ); - } }, }; diff --git a/test/cli/samples/watch/watch-config/_expected/output1.js b/test/cli/samples/watch/watch-config/_expected/output.js similarity index 100% rename from test/cli/samples/watch/watch-config/_expected/output1.js rename to test/cli/samples/watch/watch-config/_expected/output.js diff --git a/test/cli/samples/watch/watch-config/main5.js b/test/cli/samples/watch/watch-config/main5.js deleted file mode 100644 index f3ae9b95c72..00000000000 --- a/test/cli/samples/watch/watch-config/main5.js +++ /dev/null @@ -1 +0,0 @@ -export const foo = 46; diff --git a/test/cli/samples/watch/watch-config/main6.js b/test/cli/samples/watch/watch-config/main6.js deleted file mode 100644 index 927270a3a6b..00000000000 --- a/test/cli/samples/watch/watch-config/main6.js +++ /dev/null @@ -1 +0,0 @@ -export const foo = 47; diff --git a/test/cli/samples/watch/watch-config/rollup.config.js b/test/cli/samples/watch/watch-config/rollup.config.js index dfda9d9c97f..2f5615a36b2 100644 --- a/test/cli/samples/watch/watch-config/rollup.config.js +++ b/test/cli/samples/watch/watch-config/rollup.config.js @@ -1,5 +1,5 @@ export default { - input: {output3: "main6.js"}, + input: {output: "main4.js"}, output: { dir: "_actual", format: "es"