From d35c00d7291feec7c92a500a82b4077303daf981 Mon Sep 17 00:00:00 2001 From: Clark Du Date: Thu, 22 Mar 2018 17:11:16 +0800 Subject: [PATCH] feat: vue-loader next migration --- lib/builder/webpack/base.config.mjs | 11 +++-- lib/builder/webpack/client.config.mjs | 4 +- lib/builder/webpack/loaders/index.js | 3 ++ lib/builder/webpack/loaders/lodash-loader.js | 41 ++++++++++++++++++ lib/builder/webpack/style-loader.js | 31 +++++++------- lib/builder/webpack/vue-loader.mjs | 44 -------------------- lib/common/nuxt.config.js | 11 +++++ 7 files changed, 79 insertions(+), 66 deletions(-) create mode 100644 lib/builder/webpack/loaders/index.js create mode 100644 lib/builder/webpack/loaders/lodash-loader.js delete mode 100644 lib/builder/webpack/vue-loader.mjs diff --git a/lib/builder/webpack/base.config.mjs b/lib/builder/webpack/base.config.mjs index f2a37ffb77..b927613241 100644 --- a/lib/builder/webpack/base.config.mjs +++ b/lib/builder/webpack/base.config.mjs @@ -5,11 +5,12 @@ import TimeFixPlugin from 'time-fix-plugin' import webpack from 'webpack' import _ from 'lodash' +import VueLoader from 'vue-loader' import { isUrl, urlJoin } from '../../common/utils' +import customLoaders from './loaders' import WarnFixPlugin from './plugins/warnfix' import ProgressPlugin from './plugins/progress' -import vueLoader from './vue-loader' import styleLoaderWrapper from './style-loader' /* @@ -68,6 +69,7 @@ export default function webpackBaseConfig({ name, isServer }) { modules: webpackModulesDir }, resolveLoader: { + alias: customLoaders, modules: webpackModulesDir }, module: { @@ -76,7 +78,7 @@ export default function webpackBaseConfig({ name, isServer }) { { test: /\.vue$/, loader: 'vue-loader', - options: vueLoader.call(this, { isServer }) + options: _.cloneDeep(this.options.build.vue) }, { test: /\.jsx?$/, @@ -123,7 +125,10 @@ export default function webpackBaseConfig({ name, isServer }) { } ] }, - plugins: this.options.build.plugins + plugins: [ + new VueLoader.VueLoaderPlugin(), + ...(this.options.plugins || []) + ] } // Build progress indicator diff --git a/lib/builder/webpack/client.config.mjs b/lib/builder/webpack/client.config.mjs index 3a3ad9aa2d..719160e8bb 100644 --- a/lib/builder/webpack/client.config.mjs +++ b/lib/builder/webpack/client.config.mjs @@ -41,7 +41,7 @@ export default function webpackClientConfig() { config.plugins.push( new HTMLPlugin({ filename: 'index.spa.html', - template: this.options.appTemplatePath, + template: 'lodash!' + this.options.appTemplatePath, inject: true, chunksSortMode: 'dependency' }) @@ -52,7 +52,7 @@ export default function webpackClientConfig() { config.plugins.push( new HTMLPlugin({ filename: 'index.ssr.html', - template: this.options.appTemplatePath, + template: 'lodash!' + this.options.appTemplatePath, inject: false // Resources will be injected using bundleRenderer }) ) diff --git a/lib/builder/webpack/loaders/index.js b/lib/builder/webpack/loaders/index.js new file mode 100644 index 0000000000..5d4c571939 --- /dev/null +++ b/lib/builder/webpack/loaders/index.js @@ -0,0 +1,3 @@ +export default { + 'lodash': require.resolve('./lodash-loader') +} diff --git a/lib/builder/webpack/loaders/lodash-loader.js b/lib/builder/webpack/loaders/lodash-loader.js new file mode 100644 index 0000000000..eefb95e305 --- /dev/null +++ b/lib/builder/webpack/loaders/lodash-loader.js @@ -0,0 +1,41 @@ +import _ from 'lodash' +import loaderUtils from 'loader-utils' + +export default function (source) { + if (this.cacheable) { + this.cacheable() + } + + // Skip .js files + if (/\.js$/.test(this.resourcePath)) { + return source + } + + // The following part renders the tempalte with lodash as aminimalistic loader + // + // Get templating options + const options = this.query !== '' ? loaderUtils.parseQuery(this.query) : {} + // Webpack 2 does not allow with() statements, which lodash templates use to unwrap + // the parameters passed to the compiled template inside the scope. We therefore + // need to unwrap them ourselves here. This is essentially what lodash does internally + // To tell lodash it should not use with we set a variable + const template = _.template(source, _.defaults(options, { variable: 'data' })) + // All templateVariables which should be available + // @see HtmlWebpackPlugin.prototype.executeTemplate + const templateVariables = [ + 'compilation', + 'webpack', + 'webpackConfig', + 'htmlWebpackPlugin' + ] + return 'var _ = require(' + loaderUtils.stringifyRequest(this, require.resolve('lodash')) + ');' + + 'module.exports = function (templateParams) {' + + // Declare the template variables in the outer scope of the + // lodash template to unwrap them + templateVariables.map(function (variableName) { + return 'var ' + variableName + ' = templateParams.' + variableName + }).join(';') + ';' + + // Execute the lodash template + 'return (' + template.source + ')();' + + '}' +}; diff --git a/lib/builder/webpack/style-loader.js b/lib/builder/webpack/style-loader.js index 86b6cf52dd..9d60feb744 100644 --- a/lib/builder/webpack/style-loader.js +++ b/lib/builder/webpack/style-loader.js @@ -4,7 +4,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin' import postcssConfig from './postcss' -export default ({isVueLoader = false, isServer}) => { +export default ({ isServer }) => { return function styleLoader(ext, loaders = []) { const sourceMap = Boolean(this.options.build.cssSourceMap) @@ -37,17 +37,14 @@ export default ({isVueLoader = false, isServer}) => { } // postcss-loader - // vue-loader already provides it's own // https://github.com/postcss/postcss-loader - if (!isVueLoader) { - const _postcssConfig = postcssConfig.call(this) + const _postcssConfig = postcssConfig.call(this) - if (_postcssConfig) { - loaders.unshift({ - loader: 'postcss-loader', - options: Object.assign({ sourceMap }, _postcssConfig) - }) - } + if (_postcssConfig) { + loaders.unshift({ + loader: 'postcss-loader', + options: Object.assign({ sourceMap }, _postcssConfig) + }) } // css-loader @@ -66,6 +63,13 @@ export default ({isVueLoader = false, isServer}) => { } }) + // Prepare vue-style-loader + // https://github.com/vuejs/vue-style-loader + loaders.unshift({ + loader: 'vue-style-loader', + options: { sourceMap } + }) + // -- With extractCSS -- if (this.options.build.extractCSS) { if (!isServer) { @@ -79,13 +83,6 @@ export default ({isVueLoader = false, isServer}) => { }) } } - } else { - // Prepare vue-style-loader - // https://github.com/vuejs/vue-style-loader - loaders.unshift({ - loader: 'vue-style-loader', - options: { sourceMap } - }) } return loaders } diff --git a/lib/builder/webpack/vue-loader.mjs b/lib/builder/webpack/vue-loader.mjs deleted file mode 100644 index 488b605e88..0000000000 --- a/lib/builder/webpack/vue-loader.mjs +++ /dev/null @@ -1,44 +0,0 @@ -import postcssConfig from './postcss' -import styleLoaderWrapper from './style-loader' - -export default function vueLoader({ isServer }) { - // https://vue-loader.vuejs.org/en - const styleLoader = styleLoaderWrapper({ - isServer, - isVueLoader: true - }) - const config = { - postcss: postcssConfig.call(this), - cssSourceMap: this.options.build.cssSourceMap, - preserveWhitespace: false, - loaders: { - js: { - loader: 'babel-loader', - options: this.getBabelOptions({ isServer }) - }, - // Note: do not nest the `postcss` option under `loaders` - css: styleLoader.call(this, 'css', []), - less: styleLoader.call(this, 'less', 'less-loader'), - scss: styleLoader.call(this, 'scss', 'sass-loader'), - sass: styleLoader.call( - this, - 'sass', - { loader: 'sass-loader', options: { indentedSyntax: true } } - ), - stylus: styleLoader.call(this, 'stylus', 'stylus-loader'), - styl: styleLoader.call(this, 'stylus', 'stylus-loader') - }, - template: { - doctype: 'html' // For pug, see https://github.com/vuejs/vue-loader/issues/55 - }, - transformToRequire: { - video: 'src', - source: 'src', - object: 'src', - embed: 'src' - } - } - - // Return the config - return config -} diff --git a/lib/common/nuxt.config.js b/lib/common/nuxt.config.js index c185486d34..a66638fd62 100644 --- a/lib/common/nuxt.config.js +++ b/lib/common/nuxt.config.js @@ -59,6 +59,17 @@ export default { babel: { babelrc: false }, + vue: { + template: { + doctype: 'html' // For pug, see https://github.com/vuejs/vue-loader/issues/55 + }, + transformAssetUrls: { + video: 'src', + source: 'src', + object: 'src', + embed: 'src' + } + }, postcss: {}, templates: [], watch: [],