diff --git a/lib/builder/webpack/base.config.mjs b/lib/builder/webpack/base.config.mjs index 7746ec6c80..f2a37ffb77 100644 --- a/lib/builder/webpack/base.config.mjs +++ b/lib/builder/webpack/base.config.mjs @@ -1,6 +1,5 @@ import path from 'path' -import MiniCssExtractPlugin from 'mini-css-extract-plugin' import FriendlyErrorsWebpackPlugin from '@nuxtjs/friendly-errors-webpack-plugin' import TimeFixPlugin from 'time-fix-plugin' import webpack from 'webpack' @@ -11,7 +10,7 @@ import { isUrl, urlJoin } from '../../common/utils' import WarnFixPlugin from './plugins/warnfix' import ProgressPlugin from './plugins/progress' import vueLoader from './vue-loader' -import styleLoader from './style-loader' +import styleLoaderWrapper from './style-loader' /* |-------------------------------------------------------------------------- @@ -26,6 +25,7 @@ export default function webpackBaseConfig({ name, isServer }) { const webpackModulesDir = ['node_modules'].concat(this.options.modulesDir) const configAlias = {} + const styleLoader = styleLoaderWrapper({ isServer }) // Used by vue-loader so we can use in templates // with @@ -161,14 +161,6 @@ export default function webpackBaseConfig({ name, isServer }) { }) ) - // CSS extraction - const extractCSS = this.options.build.extractCSS - if (extractCSS && !this.options.dev) { - config.plugins.push(new MiniCssExtractPlugin(Object.assign({ - filename: this.getFileName('css') - }, typeof extractCSS === 'object' ? extractCSS : {}))) - } - // Clone deep avoid leaking config between Client and Server return _.cloneDeep(config) } diff --git a/lib/builder/webpack/client.config.mjs b/lib/builder/webpack/client.config.mjs index 47682b5fcc..3a3ad9aa2d 100644 --- a/lib/builder/webpack/client.config.mjs +++ b/lib/builder/webpack/client.config.mjs @@ -6,6 +6,7 @@ import webpack from 'webpack' import HTMLPlugin from 'html-webpack-plugin' import StylishPlugin from 'webpack-stylish' import BundleAnalyzer from 'webpack-bundle-analyzer' +import MiniCssExtractPlugin from 'mini-css-extract-plugin' import Debug from 'debug' import base from './base.config' @@ -154,5 +155,13 @@ export default function webpackClientConfig() { } } + // CSS extraction + const extractCSS = this.options.build.extractCSS + if (extractCSS) { + config.plugins.push(new MiniCssExtractPlugin(Object.assign({ + filename: this.getFileName('css') + }, typeof extractCSS === 'object' ? extractCSS : {}))) + } + return config } diff --git a/lib/builder/webpack/style-loader.js b/lib/builder/webpack/style-loader.js index 4d78c1378f..023acc06d5 100644 --- a/lib/builder/webpack/style-loader.js +++ b/lib/builder/webpack/style-loader.js @@ -4,85 +4,87 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin' import postcssConfig from './postcss' -export default function styleLoader(ext, loaders = [], isVueLoader = false) { - const sourceMap = Boolean(this.options.build.cssSourceMap) +export default ({isVueLoader = false, isServer}) => { + return function styleLoader(ext, loaders = []) { + const sourceMap = Boolean(this.options.build.cssSourceMap) - // Normalize loaders - loaders = (Array.isArray(loaders) ? loaders : [loaders]).map(loader => - Object.assign( - { options: { sourceMap } }, - typeof loader === 'string' ? { loader } : loader - ) - ) - - // -- Configure additional loaders -- - - // style-resources-loader - // https://github.com/yenshih/style-resources-loader - if (this.options.build.styleResources[ext]) { - const patterns = Array.isArray(this.options.build.styleResources[ext]) - ? this.options.build.styleResources[ext] - : [this.options.build.styleResources[ext]] - const options = Object.assign( - {}, - this.options.build.styleResources.options || {}, - { patterns } + // Normalize loaders + loaders = (Array.isArray(loaders) ? loaders : [loaders]).map(loader => + Object.assign( + { options: { sourceMap } }, + typeof loader === 'string' ? { loader } : loader + ) ) - loaders.push({ - loader: 'style-resources-loader', - options - }) - } + // -- Configure additional loaders -- - // postcss-loader - // vue-loader already provides it's own - // https://github.com/postcss/postcss-loader - if (!isVueLoader) { - const _postcssConfig = postcssConfig.call(this) + // style-resources-loader + // https://github.com/yenshih/style-resources-loader + if (this.options.build.styleResources[ext]) { + const patterns = Array.isArray(this.options.build.styleResources[ext]) + ? this.options.build.styleResources[ext] + : [this.options.build.styleResources[ext]] + const options = Object.assign( + {}, + this.options.build.styleResources.options || {}, + { patterns } + ) - if (_postcssConfig) { - loaders.unshift({ - loader: 'postcss-loader', - options: Object.assign({ sourceMap }, _postcssConfig) + loaders.push({ + loader: 'style-resources-loader', + options }) } - } - // css-loader - // https://github.com/webpack-contrib/css-loader - const cssLoaderAlias = {} - cssLoaderAlias[`/${this.options.dir.assets}`] = path.join(this.options.srcDir, this.options.dir.assets) - cssLoaderAlias[`/${this.options.dir.static}`] = path.join(this.options.srcDir, this.options.dir.static) + // postcss-loader + // vue-loader already provides it's own + // https://github.com/postcss/postcss-loader + if (!isVueLoader) { + const _postcssConfig = postcssConfig.call(this) - loaders.unshift({ - loader: 'css-loader', - options: { - sourceMap, - minimize: !this.options.dev, - importLoaders: loaders.length, // Important! - alias: cssLoaderAlias + if (_postcssConfig) { + loaders.unshift({ + loader: 'postcss-loader', + options: Object.assign({ sourceMap }, _postcssConfig) + }) + } } - }) - // -- With extractCSS -- - if (this.options.build.extractCSS) { - loaders.unshift(MiniCssExtractPlugin.loader) - if (this.options.dev) { - // css-hot-loader - // https://github.com/shepherdwind/css-hot-loader + // css-loader + // https://github.com/webpack-contrib/css-loader + const cssLoaderAlias = {} + cssLoaderAlias[`/${this.options.dir.assets}`] = path.join(this.options.srcDir, this.options.dir.assets) + cssLoaderAlias[`/${this.options.dir.static}`] = path.join(this.options.srcDir, this.options.dir.static) + + loaders.unshift({ + loader: 'css-loader', + options: { + sourceMap, + minimize: !this.options.dev, + importLoaders: loaders.length, // Important! + alias: cssLoaderAlias + } + }) + + // -- With extractCSS -- + if (!isServer && this.options.build.extractCSS) { + loaders.unshift(MiniCssExtractPlugin.loader) + if (this.options.dev) { + // css-hot-loader + // https://github.com/shepherdwind/css-hot-loader + loaders.unshift({ + loader: 'css-hot-loader', + options: { sourceMap } + }) + } + } else { + // Prepare vue-style-loader + // https://github.com/vuejs/vue-style-loader loaders.unshift({ - loader: 'css-hot-loader', + loader: 'vue-style-loader', options: { sourceMap } }) } - } else { - // Prepare vue-style-loader - // https://github.com/vuejs/vue-style-loader - loaders.unshift({ - loader: 'vue-style-loader', - options: { sourceMap } - }) + return loaders } - return loaders } diff --git a/lib/builder/webpack/vue-loader.mjs b/lib/builder/webpack/vue-loader.mjs index de9a864bd8..488b605e88 100644 --- a/lib/builder/webpack/vue-loader.mjs +++ b/lib/builder/webpack/vue-loader.mjs @@ -1,8 +1,12 @@ import postcssConfig from './postcss' -import styleLoader from './style-loader' +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, @@ -13,17 +17,16 @@ export default function vueLoader({ isServer }) { options: this.getBabelOptions({ isServer }) }, // Note: do not nest the `postcss` option under `loaders` - css: styleLoader.call(this, 'css', [], true), - less: styleLoader.call(this, 'less', 'less-loader', true), - scss: styleLoader.call(this, 'scss', 'sass-loader', true), + 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 } }, - true + { loader: 'sass-loader', options: { indentedSyntax: true } } ), - stylus: styleLoader.call(this, 'stylus', 'stylus-loader', true), - styl: styleLoader.call(this, 'stylus', 'stylus-loader', 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