[vue-loader] allow using builtin extractCSS functionality

This option is disabled by default and won't affect exiting users.
However users can easily enable this option using `nuxt.build.extractCSS`

Implementation is according to:
- https://github.com/vuejs/vue-loader/tree/master/docs/en/configurations
- https://ssr.vuejs.org/en/css.html
- https://github.com/vuejs/vue-hackernews-2.0/tree/master/build
This commit is contained in:
Pooya Parsa 2017-04-30 16:28:25 +04:30
parent 379fb753ca
commit 87172100c7
7 changed files with 56 additions and 14 deletions

View File

@ -1,6 +1,7 @@
module.exports = {
build: {
filenames: {
css: 'styles.[chunkhash].css', // default: common.[chunkhash].css
manifest: 'manifest.[hash].js', // default: manifest.[hash].js
vendor: 'vendor.[hash].js', // default: vendor.bundle.[hash].js
app: 'app.[chunkhash].js' // default: nuxt.bundle.[chunkhash].js

View File

@ -51,6 +51,7 @@ const defaults = {
analyze: false,
publicPath: '/_nuxt/',
filenames: {
css: 'common.[chunkhash].css',
manifest: 'manifest.[hash].js',
vendor: 'vendor.bundle.[hash].js',
app: 'nuxt.bundle.[chunkhash].js'

View File

@ -4,6 +4,8 @@ import vueLoaderConfig from './vue-loader.config'
import { defaults } from 'lodash'
import { join } from 'path'
import { isUrl, urlJoin } from '../utils'
import { styleLoader, extractStyles } from './helpers'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
/*
|--------------------------------------------------------------------------
@ -71,15 +73,21 @@ export default function ({ isClient, isServer }) {
cacheDirectory: !!this.dev
})
},
{ test: /\.css$/, loader: 'vue-style-loader!css-loader' },
{ test: /\.less$/, loader: 'vue-style-loader!css-loader!less-loader' },
{ test: /\.sass$/, loader: 'vue-style-loader!css-loader!sass-loader?indentedSyntax' },
{ test: /\.scss$/, loader: 'vue-style-loader!css-loader!sass-loader' },
{ test: /\.styl(us)?$/, loader: 'vue-style-loader!css-loader!stylus-loader' }
{ test: /\.css$/, use: styleLoader.call(this, 'css') },
{ test: /\.less$/, use: styleLoader.call(this, 'less', 'less-loader') },
{ test: /\.sass$/, use: styleLoader.call(this, 'sass', 'sass-loader?indentedSyntax') },
{ test: /\.scss$/, use: styleLoader.call(this, 'sass', 'sass-loader') },
{ test: /\.styl(us)?$/, use: styleLoader.call(this, 'stylus', 'stylus-loader') }
]
},
plugins: this.options.build.plugins
}
// CSS extraction
if (extractStyles.call(this)) {
config.plugins.push(
new ExtractTextPlugin({filename: this.options.build.filenames.css})
)
}
// Add nuxt build loaders (can be configured in nuxt.config.js)
config.module.rules = config.module.rules.concat(this.options.build.loaders)
// Return config

View File

@ -3,12 +3,14 @@
import { each, defaults } from 'lodash'
import webpack from 'webpack'
import VueSSRClientPlugin from 'vue-server-renderer/client-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
import HTMLPlugin from 'html-webpack-plugin'
import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin'
import ProgressBarPlugin from 'progress-bar-webpack-plugin'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
import OfflinePlugin from 'offline-plugin'
import base from './base.config.js'
import { extractStyles } from './helpers'
import { resolve } from 'path'
/*
@ -55,9 +57,18 @@ export default function () {
// Extract vendor chunks for better caching
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: this.options.build.filenames.vendor
filename: this.options.build.filenames.vendor,
minChunks (module) {
// A module is extracted into the vendor chunk when...
return (
// If it's inside node_modules
/node_modules/.test(module.context) &&
// Do not externalize if the request is a CSS file
!/\.css$/.test(module.request)
)
}
}),
// Extract manifest
// Extract webpack runtime & manifest
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity,
@ -68,6 +79,7 @@ export default function () {
template: this.options.appTemplatePath,
inject: false // <- Resources will be injected using vue server renderer
}),
// Generate client manifest json
new VueSSRClientPlugin({
filename: 'client-manifest.json'
})

15
lib/webpack/helpers.js Executable file
View File

@ -0,0 +1,15 @@
import ExtractTextPlugin from 'extract-text-webpack-plugin'
export function extractStyles(ext) {
return !this.dev && !!this.options.build.extractCSS && this.options.build.extractCSS[ext] !== false
}
export function styleLoader(ext, loader = []) {
if (!extractStyles.call(this, ext)) {
return ['vue-style-loader', 'css-loader'].concat(loader)
}
return ExtractTextPlugin.extract({
use: ['css-loader?minimize'].concat(loader),
fallback: 'vue-style-loader'
})
}

View File

@ -1,6 +1,7 @@
'use strict'
import { defaults } from 'lodash'
import { extractStyles, styleLoader } from './helpers'
export default function ({ isClient }) {
let babelOptions = JSON.stringify(defaults(this.options.build.babel, {
@ -8,18 +9,21 @@ export default function ({ isClient }) {
babelrc: false,
cacheDirectory: !!this.dev
}))
// https://github.com/vuejs/vue-loader/blob/master/docs/en/configurations
let config = {
postcss: this.options.build.postcss,
loaders: {
'js': 'babel-loader?' + babelOptions,
'css': 'vue-style-loader!css-loader',
'less': 'vue-style-loader!css-loader!less-loader',
'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
'scss': 'vue-style-loader!css-loader!sass-loader',
'stylus': 'vue-style-loader!css-loader!stylus-loader',
'styl': 'vue-style-loader!css-loader!stylus-loader'
'css': styleLoader.call(this, 'css'),
'less': styleLoader.call(this, 'less', 'less-loader'),
'sass': styleLoader.call(this, 'sass', 'sass-loader?indentedSyntax'),
'scss': styleLoader.call(this, 'sass', 'scss-loader'),
'stylus': styleLoader.call(this, 'stylus', 'stylus-loader'),
'styl': styleLoader.call(this, 'stylus', 'stylus-loader')
},
preserveWhitespace: false
preserveWhitespace: false,
extractCSS: extractStyles.call(this, 'vue')
}
// Return the config
return config

View File

@ -62,6 +62,7 @@
"compression": "^1.6.2",
"css-loader": "^0.28.0",
"debug": "^2.6.6",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.11.1",
"friendly-errors-webpack-plugin": "^1.6.1",
"fs-extra": "^3.0.0",