From 5501d215e81631813bb03f89eadfa28dfa7ecb88 Mon Sep 17 00:00:00 2001 From: crayon Date: Mon, 26 Aug 2019 23:17:11 +0800 Subject: [PATCH] fix: rollup watch #148 --- packages/remax-cli/package.json | 1 + packages/remax-cli/src/build/index.ts | 56 +++--------- packages/remax-cli/src/build/utils/output.ts | 14 +++ packages/remax-cli/src/build/watcher.ts | 89 ++++++++++++++++++++ packages/remax-cli/src/getEntries.ts | 12 ++- 5 files changed, 124 insertions(+), 48 deletions(-) create mode 100644 packages/remax-cli/src/build/utils/output.ts create mode 100644 packages/remax-cli/src/build/watcher.ts diff --git a/packages/remax-cli/package.json b/packages/remax-cli/package.json index 4f9c50d2a..e798028c4 100644 --- a/packages/remax-cli/package.json +++ b/packages/remax-cli/package.json @@ -28,6 +28,7 @@ "@remax/postcss-px2units": "^0.2.0", "acorn-walk": "^7.0.0", "babel-plugin-transform-async-to-promises": "^0.8.14", + "chokidar": "^3.0.2", "commander": "^2.19.0", "ejs": "^2.6.1", "lodash": "^4.17.11", diff --git a/packages/remax-cli/src/build/index.ts b/packages/remax-cli/src/build/index.ts index a96b14198..4ef4bddd6 100644 --- a/packages/remax-cli/src/build/index.ts +++ b/packages/remax-cli/src/build/index.ts @@ -2,21 +2,8 @@ import * as rollup from 'rollup'; import rollupConfig from './rollupConfig'; import getConfig from '../getConfig'; import { Context } from '../types'; - -const COLORS = { - red: '\x1b[31m', - green: '\x1b[32m', - blue: '\x1b[34m', -}; -const RESET = '\x1b[0m'; - -const output = ( - content: string | string[], - color: 'red' | 'green' | 'blue' -) => { - const message = Array.isArray(content) ? content : [content]; - console.log(`${COLORS[color]}%s${RESET}`, ...message); -}; +import runWatcher from './watcher'; +import { output } from './utils/output'; export default async (argv: any, context?: Context) => { const options = { @@ -32,38 +19,15 @@ export default async (argv: any, context?: Context) => { throw new Error(`Target ${argv.target} is not supported yet.`); } - const rollupOptions = rollupConfig(options, argv, targetConfig, context); - if (argv.watch) { - const watcher = rollup.watch([ - { - ...rollupOptions, - watch: { - include: ['src/**', 'app.js', '*.config.js'], - }, - }, - ]); - - console.log('\x1b[34m%s\x1b[0m', '๐Ÿš€ ๅฏๅŠจ watch'); + const rollupOptions: rollup.RollupOptions = rollupConfig( + options, + argv, + targetConfig, + context + ); - watcher.on('event', (event: any) => { - switch (event.code) { - case 'START': - output('๐Ÿšš ็ผ–่ฏ‘...', 'blue'); - break; - case 'END': - output('๐Ÿ’ก ๅฎŒๆˆ', 'green'); - break; - case 'ERROR': - case 'FATAL': - const { error } = event; - const name = - error.code === 'PLUGIN_ERROR' ? error.plugin : error.code; - output(`\n๐Ÿšจ [${name}]: ${error.message}`, 'red'); - throw error; - default: - break; - } - }); + if (argv.watch) { + runWatcher(rollupOptions); } else { try { output('๐Ÿš€ ๅผ€ๅง‹ build...', 'blue'); diff --git a/packages/remax-cli/src/build/utils/output.ts b/packages/remax-cli/src/build/utils/output.ts new file mode 100644 index 000000000..aa628b7df --- /dev/null +++ b/packages/remax-cli/src/build/utils/output.ts @@ -0,0 +1,14 @@ +const COLORS = { + red: '\x1b[31m', + green: '\x1b[32m', + blue: '\x1b[34m', +}; +const RESET = '\x1b[0m'; + +export const output = ( + content: string | string[], + color: 'red' | 'green' | 'blue' +) => { + const message = Array.isArray(content) ? content : [content]; + console.log(`${COLORS[color]}%s${RESET}`, ...message); +}; diff --git a/packages/remax-cli/src/build/watcher.ts b/packages/remax-cli/src/build/watcher.ts new file mode 100644 index 000000000..a5e295a60 --- /dev/null +++ b/packages/remax-cli/src/build/watcher.ts @@ -0,0 +1,89 @@ +import fs from 'fs'; +import chokidar from 'chokidar'; +import { RollupOptions, watch, RollupWatcher } from 'rollup'; +import { output } from './utils/output'; + +let isBundleRunning = false; +let isFirstRunWatcher = true; + +const rollupWatchFiles = ['src/**', 'app.js']; +// ้…็ฝฎ้‡ๆ–ฐbuild็š„่ทฏๅพ„ +const extraFiles = ['src/app.config.js']; + +let extraFilesWatcher: RollupWatcher; + +let watcher: RollupWatcher; +export default function runWather(rollupOptions: RollupOptions) { + if (isBundleRunning) { + return; + } + + isBundleRunning = true; + + watcher = watch([ + { + ...rollupOptions, + watch: { + chokidar: { + usePolling: true, + }, + include: rollupWatchFiles, + }, + }, + ]); + + const watchEventHandle = (event: any) => { + switch (event.code) { + case 'START': + output('๐Ÿšš ็ผ–่ฏ‘...', 'blue'); + break; + case 'END': + isBundleRunning = false; + output('๐Ÿ’ก ๅฎŒๆˆ', 'green'); + break; + case 'ERROR': + case 'FATAL': + isBundleRunning = false; + const { error } = event; + const name = error.code === 'PLUGIN_ERROR' ? error.plugin : error.code; + output(`\n๐Ÿšจ [${name}]: ${error.message}`, 'red'); + throw error; + default: + break; + } + }; + + watcher.on('event', watchEventHandle); + + if (isFirstRunWatcher) { + isFirstRunWatcher = false; + console.log('\x1b[34m%s\x1b[0m', '๐Ÿš€ ๅฏๅŠจ watch'); + } + + const close = (err?: Error) => { + if (watcher) watcher.close(); + if (extraFilesWatcher) extraFilesWatcher.close(); + + process.removeListener('uncaughtException', close); + + if (err) { + process.exit(1); + console.error(err); + } + }; + + process.on('uncaughtException', close); + // ็›‘ๅฌ้ขๅค–็š„ๆ–‡ไปถ + extraFilesWatcher = chokidar.watch(extraFiles); + + extraFilesWatcher + .on('add', () => { + if (isFirstRunWatcher || isBundleRunning) return; + runWather(rollupOptions); + }) + .on('unlink', () => { + if (isFirstRunWatcher || isBundleRunning) return; + runWather(rollupOptions); + }) + .on('change', () => runWather(rollupOptions)); +} diff --git a/packages/remax-cli/src/getEntries.ts b/packages/remax-cli/src/getEntries.ts index 70a20f877..7a304d788 100644 --- a/packages/remax-cli/src/getEntries.ts +++ b/packages/remax-cli/src/getEntries.ts @@ -74,11 +74,15 @@ export default function getEntries( entries.pages = pages.reduce( (ret: Array<{ path: string; file: string }>, page: string) => { + const file = searchFile(path.join(options.cwd, 'src', page)); + if (!file) { + throw new Error(`Could not resolve page module (${page}).`); + } return [ ...ret, { path: page, - file: searchFile(path.join(options.cwd, 'src', page)), + file, }, ].filter(page => page && page.file); }, @@ -88,11 +92,15 @@ export default function getEntries( subpackages.forEach((pack: { pages: string[]; root: string }) => { entries.pages = entries.pages.concat( pack.pages.reduce((ret: Array<{ path: string; file: string }>, page) => { + const file = searchFile(path.join(options.cwd, 'src', pack.root, page)); + if (!file) { + throw new Error(`Could not resolve page module (${page}).`); + } return [ ...ret, { path: page, - file: searchFile(path.join(options.cwd, 'src', pack.root, page)), + file, }, ].filter(page => page && page.file); }, [])