Merge pull request #3077 from nuxt/feat/mini-css-extract

feat: migrate to mini-css-extract-plugin
This commit is contained in:
Clark Du 2018-03-22 17:01:27 +08:00 committed by GitHub
commit 531b2ec37c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 109 additions and 111 deletions

View File

@ -1,6 +1,5 @@
import path from 'path'
import ExtractTextPlugin from 'extract-text-webpack-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 <img src="~/assets/nuxt.png"/>
@ -161,17 +161,6 @@ export default function webpackBaseConfig({ name, isServer }) {
})
)
// CSS extraction
const extractCSS = this.options.build.extractCSS
// TODO: Temporary disabled in dev mode for fixing source maps
// (We need `source-map` devtool for *.css modules)
if (extractCSS && !this.options.dev) {
config.plugins.push(new ExtractTextPlugin(Object.assign({
filename: this.getFileName('css'),
allChunks: true
}, typeof extractCSS === 'object' ? extractCSS : {})))
}
// Clone deep avoid leaking config between Client and Server
return _.cloneDeep(config)
}

View File

@ -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
}

View File

@ -1,98 +1,92 @@
import path from 'path'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
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
)
)
// Prepare vue-style-loader
// https://github.com/vuejs/vue-style-loader
const vueStyleLoader = {
loader: 'vue-style-loader',
options: { sourceMap }
}
// -- 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 --
// TODO: Temporary disabled in dev mode for fixing source maps
// (We need `source-map` devtool for *.css modules)
if (this.options.build.extractCSS && !this.options.dev) {
// ExtractTextPlugin
// https://github.com/webpack-contrib/extract-text-webpack-plugin
const extractLoader = ExtractTextPlugin.extract({
use: loaders,
fallback: vueStyleLoader
// 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
}
})
// css-hot-loader
// https://github.com/shepherdwind/css-hot-loader
const hotLoader = {
loader: 'css-hot-loader',
options: { sourceMap }
// -- With extractCSS --
if (this.options.build.extractCSS) {
if (!isServer) {
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: 'vue-style-loader',
options: { sourceMap }
})
}
return this.options.dev ? [hotLoader].concat(extractLoader) : extractLoader
return loaders
}
// -- Without extractCSS --
return [vueStyleLoader].concat(loaders)
}

View File

@ -1,11 +1,14 @@
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),
extractCSS: !!this.options.build.extractCSS,
cssSourceMap: this.options.build.cssSourceMap,
preserveWhitespace: false,
loaders: {
@ -14,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

View File

@ -39,7 +39,9 @@ export default {
filenames: {
app: '[name].[chunkhash].js',
chunk: '[name].[chunkhash].js',
css: '[name].[contenthash].css'
// TODO: Use [name].[contenthash].css when webpack core supports [contenthash]
// https://github.com/webpack-contrib/mini-css-extract-plugin/pull/30#issuecomment-374700690
css: '[name].[chunkhash].css'
},
styleResources: {},
plugins: [],

View File

@ -174,5 +174,9 @@ Options.from = function (_options) {
options.generate.fallback = '404.html'
}
// TODO: remove when mini-css-extract-plugin supports HMR
if (options.dev) {
options.build.extractCSS = false
}
return options
}

View File

@ -72,7 +72,6 @@
"es6-promise": "^4.2.4",
"esm": "^3.0.7",
"etag": "^1.8.1",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^1.1.11",
"fresh": "^0.5.2",
"fs-extra": "^5.0.0",
@ -85,6 +84,7 @@
"lodash": "^4.17.5",
"lru-cache": "^4.1.2",
"memory-fs": "^0.4.1",
"mini-css-extract-plugin": "^0.2.0",
"minimist": "^1.2.0",
"opencollective": "^1.0.3",
"ora": "^2.0.0",

View File

@ -385,7 +385,7 @@ async@^1.4.0:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
async@^2.1.4, async@^2.4.1:
async@^2.1.4:
version "2.6.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
dependencies:
@ -2686,15 +2686,6 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
extract-text-webpack-plugin@^4.0.0-beta.0:
version "4.0.0-beta.0"
resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz#f7361d7ff430b42961f8d1321ba8c1757b5d4c42"
dependencies:
async "^2.4.1"
loader-utils "^1.1.0"
schema-utils "^0.4.5"
webpack-sources "^1.1.0"
extract-zip@^1.6.5:
version "1.6.6"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c"
@ -4611,6 +4602,13 @@ mimic-fn@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
mini-css-extract-plugin@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.2.0.tgz#7a16b0e1096c86de8e4d1c3b063aa1aeae88d41d"
dependencies:
loader-utils "^1.1.0"
webpack-sources "^1.1.0"
minimalistic-assert@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"