perf: better vendor chunk

Also disables commons chunk plugin on dev environments for faster builds
This commit is contained in:
Pooya Parsa 2017-11-07 15:35:41 +03:30
parent 312ce81a6e
commit e5017c5e2a
2 changed files with 78 additions and 78 deletions

View File

@ -27,52 +27,9 @@ debug.color = 2 // Force green color
export default function webpackClientConfig() {
let config = base.call(this, 'client')
// App entry
// Entry points
config.entry.app = resolve(this.options.buildDir, 'client.js')
config.entry.common = this.vendor()
// Extract vendor chunks for better caching
const _this = this
const totalPages = _this.routes ? _this.routes.length : 0
// This well-known vendor may exist as a dependency of other requests.
const maybeVendor = [
'/core-js/',
'/regenerator-runtime/',
'/es6-promise/',
'/babel-runtime/',
'/lodash/'
]
config.plugins.push(
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
filename: this.options.build.filenames.vendor,
minChunks(module, count) {
// In the dev we use on-demand-entries.
// So, it makes no sense to use commonChunks based on the minChunks count.
// Instead, we move all the code in node_modules into each of the pages.
if (_this.options.dev) {
return false
}
// Detect and externalize well-known vendor if detected
if (module.context && maybeVendor.some(v => module.context.includes(v))) {
return true
}
// 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|less|scss|sass|styl|stylus)$/.test(module.request) &&
// Used in at-least 1/2 of the total pages
(totalPages <= 2 ? count >= totalPages : count >= totalPages * 0.5)
)
}
})
)
config.entry.vendor = this.vendor()
// Env object defined in nuxt.config.js
let env = {}
@ -80,12 +37,6 @@ export default function webpackClientConfig() {
env['process.env.' + key] = (['boolean', 'number'].indexOf(typeof value) !== -1 ? value : JSON.stringify(value))
})
// Webpack common plugins
/* istanbul ignore if */
if (!Array.isArray(config.plugins)) {
config.plugins = []
}
// Generate output HTML for SPA
config.plugins.push(
new HTMLPlugin({
@ -163,26 +114,8 @@ export default function webpackClientConfig() {
)
// DllReferencePlugin
// https://github.com/webpack/webpack/tree/master/examples/dll-user
if (this.options.build.dll) {
const _dlls = []
const vendorEntries = this.vendorEntries()
const dllDir = resolve(this.options.cacheDir, config.name + '-dll')
Object.keys(vendorEntries).forEach(v => {
const dllManifestFile = resolve(dllDir, v + '-manifest.json')
if (existsSync(dllManifestFile)) {
_dlls.push(v)
config.plugins.push(
new webpack.DllReferencePlugin({
// context: this.options.rootDir,
manifest: dllManifestFile // Using full path to allow finding .js dll file
})
)
}
})
if (_dlls.length) {
debug('Using dll for ' + _dlls.join(','))
}
dllPlugin.call(this, config)
}
}
@ -190,10 +123,13 @@ export default function webpackClientConfig() {
// Production specific config
// --------------------------------------
if (!this.options.dev) {
// Add CommonChunks plugin
commonChunksPlugin.call(this, config)
// Scope Hoisting
config.plugins.push(
// new webpack.optimize.ModuleConcatenationPlugin()
)
if (this.options.build.scopeHoisting === true) {
config.plugins.push(new webpack.optimize.ModuleConcatenationPlugin())
}
// https://webpack.js.org/plugins/hashed-module-ids-plugin
config.plugins.push(new webpack.HashedModuleIdsPlugin())
@ -212,9 +148,7 @@ export default function webpackClientConfig() {
// Webpack Bundle Analyzer
if (this.options.build.analyze) {
config.plugins.push(
new BundleAnalyzerPlugin(Object.assign({}, this.options.build.analyze))
)
config.plugins.push(new BundleAnalyzerPlugin(Object.assign({}, this.options.build.analyze)))
}
}
@ -237,3 +171,68 @@ export default function webpackClientConfig() {
return config
}
// --------------------------------------------------------------------------
// Adds Common Chunks Plugin
// --------------------------------------------------------------------------
function commonChunksPlugin(config) {
const _this = this
const totalPages = _this.routes ? _this.routes.length : 0
// This well-known vendor may exist as a dependency of other requests.
const maybeVendor = [
'/core-js/',
'/regenerator-runtime/',
'/es6-promise/',
'/babel-runtime/',
'/lodash/'
]
// Create explicit vendor chunk
config.plugins.unshift(
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: this.options.build.filenames.vendor,
minChunks(module, count) {
// Detect and externalize well-known vendor if detected
if (module.context && maybeVendor.some(v => module.context.includes(v))) {
return true
}
// 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|less|scss|sass|styl|stylus)$/.test(module.request) &&
// Used in at-least 1/2 of the total pages
(totalPages <= 2 ? count >= totalPages : count >= totalPages * 0.5)
)
}
})
)
}
// --------------------------------------------------------------------------
// Adds DLL plugin
// https://github.com/webpack/webpack/tree/master/examples/dll-user
// --------------------------------------------------------------------------
function dllPlugin(config) {
const _dlls = []
const vendorEntries = this.vendorEntries()
const dllDir = resolve(this.options.cacheDir, config.name + '-dll')
Object.keys(vendorEntries).forEach(v => {
const dllManifestFile = resolve(dllDir, v + '-manifest.json')
if (existsSync(dllManifestFile)) {
_dlls.push(v)
config.plugins.push(
new webpack.DllReferencePlugin({
// context: this.options.rootDir,
manifest: dllManifestFile // Using full path to allow finding .js dll file
})
)
}
})
if (_dlls.length) {
debug('Using dll for ' + _dlls.join(','))
}
}

View File

@ -185,14 +185,15 @@ Options.defaults = {
build: {
analyze: false,
dll: false,
scopeHoisting: false,
extractCSS: false,
cssSourceMap: undefined,
ssr: undefined,
publicPath: '/_nuxt/',
filenames: {
css: 'common.[contenthash].css',
css: 'vendor.[contenthash].css',
manifest: 'manifest.[hash].js',
vendor: 'common.[chunkhash].js',
vendor: 'vendor.[chunkhash].js',
app: 'app.[chunkhash].js',
chunk: '[name].[chunkhash].js'
},