From b8f24872bf42136ee1e53939859d9902e2363243 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 29 Jan 2018 16:23:02 -0500 Subject: [PATCH] feat: parallel mode --- packages/@vue/cli-plugin-babel/index.js | 28 +++-- packages/@vue/cli-plugin-typescript/index.js | 108 +++++++++---------- packages/@vue/cli-service/lib/options.js | 12 ++- packages/@vue/cli-service/package.json | 1 + yarn.lock | 35 ++---- 5 files changed, 91 insertions(+), 93 deletions(-) diff --git a/packages/@vue/cli-plugin-babel/index.js b/packages/@vue/cli-plugin-babel/index.js index ec4b3e2b7..c82c532ae 100644 --- a/packages/@vue/cli-plugin-babel/index.js +++ b/packages/@vue/cli-plugin-babel/index.js @@ -1,8 +1,9 @@ -module.exports = api => { +module.exports = (api, options) => { + const useThreads = process.env.NODE_ENV === 'production' && options.parallel const cacheDirectory = api.resolve('node_modules/.cache/cache-loader') api.chainWebpack(webpackConfig => { - webpackConfig.module + const jsRule = webpackConfig.module .rule('js') .test(/\.jsx?$/) .include @@ -13,8 +14,16 @@ module.exports = api => { .loader('cache-loader') .options({ cacheDirectory }) .end() - .use('babel-loader') - .loader('babel-loader') + + if (useThreads) { + jsRule + .use('thread-loader') + .loader('thread-loader') + } + + jsRule + .use('babel-loader') + .loader('babel-loader') webpackConfig.module .rule('vue') @@ -25,11 +34,16 @@ module.exports = api => { { loader: 'cache-loader', options: { cacheDirectory } - }, - { - loader: 'babel-loader' } ] + if (useThreads) { + options.loaders.js.push({ + loader: 'thread-loader' + }) + } + options.loaders.js.push({ + loader: 'babel-loader' + }) return options }) }) diff --git a/packages/@vue/cli-plugin-typescript/index.js b/packages/@vue/cli-plugin-typescript/index.js index 4a2a797cf..3605d591f 100644 --- a/packages/@vue/cli-plugin-typescript/index.js +++ b/packages/@vue/cli-plugin-typescript/index.js @@ -1,4 +1,9 @@ -module.exports = (api, options) => { +module.exports = (api, { + parallel, + lintOnSave, + experimentalCompileTsWithBabel +}) => { + const useThreads = process.env.NODE_ENV === 'production' && parallel const cacheDirectory = api.resolve('node_modules/.cache/cache-loader') api.chainWebpack(config => { @@ -17,82 +22,69 @@ module.exports = (api, options) => { .add(api.resolve('src')) .add(api.resolve('test')) .end() - .use('cache-loader') - .loader('cache-loader') - .options({ cacheDirectory }) - .end() const vueLoader = config.module .rule('vue') .use('vue-loader') - .tap(options => { - options.loaders = options.loaders || {} - options.loaders.ts = [ - { - loader: 'cache-loader', - options: { cacheDirectory } - } - ] - return options - }) - if (!options.experimentalCompileTsWithBabel) { - const tsLoaderOptions = { - transpileOnly: true, - appendTsSuffixTo: [/\.vue$/] + // add a loader to both *.ts & vue + const addLoader = loader => { + const use = tsRule + .use(loader.loader) + .loader(loader.loader) + if (loader.options) { + use.options(loader.options) } + vueLoader.tap(options => { + options.loaders = options.loaders || {} + options.loaders.ts = options.loaders.ts || [] + options.loaders.ts.push(loader) + return options + }) + } - // if has babel plugin, inject babel-loader before ts-loader + addLoader({ + loader: 'cache-loader', + options: { cacheDirectory } + }) + if (useThreads) { + addLoader({ + loader: 'thread-loader' + }) + } + + if (!experimentalCompileTsWithBabel) { if (api.hasPlugin('babel')) { - tsRule - .use('babel-loader') - .loader('babel-loader') - vueLoader - .tap(options => { - options.loaders.ts.push({ - loader: 'babel-loader' - }) - return options - }) - } - - // apply ts-loader - tsRule - .use('ts-loader') - .loader('ts-loader') - .options(tsLoaderOptions) - vueLoader - .tap(options => { - options.loaders.ts.push({ - loader: 'ts-loader', - options: tsLoaderOptions - }) - return options + addLoader({ + loader: 'babel-loader' }) + } + addLoader({ + loader: 'ts-loader', + options: { + transpileOnly: true, + appendTsSuffixTo: [/\.vue$/], + // https://github.com/TypeStrong/ts-loader#happypackmode-boolean-defaultfalse + happyPackMode: useThreads + } + }) } else { // Experimental: compile TS with babel so that it can leverage // preset-env for auto-detected polyfills based on browserslists config. // this is pending on the readiness of @babel/preset-typescript. - tsRule - .use('babel-loader') - .loader('babel-loader') - vueLoader - .tap(options => { - options.loaders.ts.push( - { - loader: 'babel-loader' - } - ) - return options - }) + addLoader({ + loader: 'babel-loader' + }) } config .plugin('fork-ts-checker') .use(require('fork-ts-checker-webpack-plugin'), [{ vue: true, - tslint: options.lintOnSave, - formatter: 'codeframe' + tslint: lintOnSave, + formatter: 'codeframe', + // https://github.com/TypeStrong/ts-loader#happypackmode-boolean-defaultfalse + checkSyntacticErrors: useThreads }]) }) diff --git a/packages/@vue/cli-service/lib/options.js b/packages/@vue/cli-service/lib/options.js index 7366c50ce..f8bcf6dbc 100644 --- a/packages/@vue/cli-service/lib/options.js +++ b/packages/@vue/cli-service/lib/options.js @@ -6,6 +6,7 @@ const schema = createSchema(joi => joi.object({ compiler: joi.boolean(), productionSourceMap: joi.boolean(), vueLoader: joi.object(), + parallel: joi.boolean(), dll: joi.alternatives().try( joi.boolean(), joi.array().items(joi.string()) @@ -22,8 +23,7 @@ const schema = createSchema(joi => joi.object({ }), devServer: joi.object(), // known options from offical plugins - lintOnSave: joi.boolean(), - pwa: joi.object() + lintOnSave: joi.boolean() })) exports.validate = options => validate( @@ -49,6 +49,14 @@ exports.defaults = () => ({ // sourceMap for production build? productionSourceMap: true, + // use thread-loader for babel & TS in production build + // enabled by default if the machine has more than 1 cores + parallel: require('os').cpus().length > 1, + + // split vendors using autoDLLPlugin? + // can be an explicit list of dependencies to include in the DLL chunk. + dll: false, + css: { // boolean | Object, extract css? extract: true, diff --git a/packages/@vue/cli-service/package.json b/packages/@vue/cli-service/package.json index 7372e6605..6c987838f 100644 --- a/packages/@vue/cli-service/package.json +++ b/packages/@vue/cli-service/package.json @@ -52,6 +52,7 @@ "slash": "^1.0.0", "source-map-url": "^0.4.0", "string.prototype.padend": "^3.0.0", + "thread-loader": "^1.1.2", "uglifyjs-webpack-plugin": "^1.1.6", "url-loader": "^0.6.2", "vue-loader": "^13.7.0", diff --git a/yarn.lock b/yarn.lock index b3a816822..e83209d59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1068,7 +1068,7 @@ async@^1.4.0, async@^1.5.0, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.1.2, async@^2.1.4, async@^2.4.0, async@^2.4.1: +async@^2.1.2, async@^2.1.4, async@^2.3.0, async@^2.4.0, async@^2.4.1: version "2.6.0" resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" dependencies: @@ -6112,31 +6112,6 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -lint-staged@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-6.1.0.tgz#28f600c10a6cbd249ceb003118a1552e53544a93" - dependencies: - app-root-path "^2.0.0" - chalk "^2.1.0" - commander "^2.11.0" - cosmiconfig "^4.0.0" - debug "^3.1.0" - dedent "^0.7.0" - execa "^0.8.0" - find-parent-dir "^0.3.0" - is-glob "^4.0.0" - jest-validate "^21.1.0" - listr "^0.13.0" - lodash "^4.17.4" - log-symbols "^2.0.0" - minimatch "^3.0.0" - npm-which "^3.0.1" - p-map "^1.1.1" - path-is-inside "^1.0.2" - pify "^3.0.0" - staged-git-files "0.0.4" - stringify-object "^3.2.0" - lint-staged@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-6.0.1.tgz#855f2993ab4a265430e2fd9828427e648d65e6b4" @@ -9467,6 +9442,14 @@ text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" +thread-loader@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/thread-loader/-/thread-loader-1.1.2.tgz#45dd1af01d8e421e6002b3c19358650cb9a42518" + dependencies: + async "^2.3.0" + loader-runner "^2.3.0" + loader-utils "^1.1.0" + throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"