mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
feat: experimental dll support
`.cache/` should be git ignored in projects. disabled by default. Can be enabled using `options.build.dll: true`
This commit is contained in:
parent
d1a6b2bc80
commit
d7fbe47c31
@ -10,11 +10,12 @@ import Tapable from 'tappable'
|
|||||||
import MFS from 'memory-fs'
|
import MFS from 'memory-fs'
|
||||||
import webpackDevMiddleware from 'webpack-dev-middleware'
|
import webpackDevMiddleware from 'webpack-dev-middleware'
|
||||||
import webpackHotMiddleware from 'webpack-hot-middleware'
|
import webpackHotMiddleware from 'webpack-hot-middleware'
|
||||||
import { r, wp, wChunk, createRoutes, parallel, relativeTo, isPureObject } from 'utils'
|
import { r, wp, wChunk, createRoutes, sequence, relativeTo, isPureObject } from 'utils'
|
||||||
import Debug from 'debug'
|
import Debug from 'debug'
|
||||||
import Glob from 'glob'
|
import Glob from 'glob'
|
||||||
import clientWebpackConfig from './webpack/client.config.js'
|
import clientWebpackConfig from './webpack/client.config.js'
|
||||||
import serverWebpackConfig from './webpack/server.config.js'
|
import serverWebpackConfig from './webpack/server.config.js'
|
||||||
|
import dllWebpackConfig from './webpack/dll.config.js'
|
||||||
import vueLoaderConfig from './webpack/vue-loader.config'
|
import vueLoaderConfig from './webpack/vue-loader.config'
|
||||||
import styleLoader from './webpack/style-loader'
|
import styleLoader from './webpack/style-loader'
|
||||||
|
|
||||||
@ -66,6 +67,29 @@ export default class Builder extends Tapable {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vendor () {
|
||||||
|
return [
|
||||||
|
'vue',
|
||||||
|
'vue-router',
|
||||||
|
'vue-meta',
|
||||||
|
'core-js',
|
||||||
|
'regenerator-runtime',
|
||||||
|
'es6-promise',
|
||||||
|
'babel-runtime',
|
||||||
|
'vuex'
|
||||||
|
].concat(this.options.build.vendor).filter(v => v)
|
||||||
|
}
|
||||||
|
|
||||||
|
vendorEntries () {
|
||||||
|
// Used for dll
|
||||||
|
const vendor = this.vendor()
|
||||||
|
const vendorEntries = {}
|
||||||
|
vendor.forEach(v => {
|
||||||
|
vendorEntries[v] = [ v ]
|
||||||
|
})
|
||||||
|
return vendorEntries
|
||||||
|
}
|
||||||
|
|
||||||
forGenerate () {
|
forGenerate () {
|
||||||
this.isStatic = true
|
this.isStatic = true
|
||||||
}
|
}
|
||||||
@ -361,6 +385,11 @@ export default class Builder extends Tapable {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Make a dll plugin after compile to make next dev builds faster
|
||||||
|
if (this.options.build.dll && this.options.dev) {
|
||||||
|
compilersOptions.push(dllWebpackConfig.call(this, clientConfig))
|
||||||
|
}
|
||||||
|
|
||||||
// Simulate webpack multi compiler interface
|
// Simulate webpack multi compiler interface
|
||||||
// Separate compilers are simpler, safer and faster
|
// Separate compilers are simpler, safer and faster
|
||||||
this.compiler = { compilers: [] }
|
this.compiler = { compilers: [] }
|
||||||
@ -377,7 +406,7 @@ export default class Builder extends Tapable {
|
|||||||
// Initialize compilers
|
// Initialize compilers
|
||||||
compilersOptions.forEach(compilersOption => {
|
compilersOptions.forEach(compilersOption => {
|
||||||
const compiler = webpack(compilersOption)
|
const compiler = webpack(compilersOption)
|
||||||
if (sharedFS) {
|
if (sharedFS && !compiler.name.includes('-dll')) {
|
||||||
compiler.outputFileSystem = sharedFS
|
compiler.outputFileSystem = sharedFS
|
||||||
}
|
}
|
||||||
compiler.cache = sharedCache
|
compiler.cache = sharedCache
|
||||||
@ -398,6 +427,9 @@ export default class Builder extends Tapable {
|
|||||||
if (stats.hasErrors()) {
|
if (stats.hasErrors()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log(stats.toString({ chunks: true }))
|
||||||
|
|
||||||
// Reload renderer if available
|
// Reload renderer if available
|
||||||
if (this.nuxt.renderer) {
|
if (this.nuxt.renderer) {
|
||||||
this.nuxt.renderer.loadResources(sharedFS || fs)
|
this.nuxt.renderer.loadResources(sharedFS || fs)
|
||||||
@ -414,12 +446,21 @@ export default class Builder extends Tapable {
|
|||||||
await this.applyPluginsAsync('compile', { builder: this, compiler: this.compiler })
|
await this.applyPluginsAsync('compile', { builder: this, compiler: this.compiler })
|
||||||
|
|
||||||
// Start Builds
|
// Start Builds
|
||||||
await parallel(this.compiler.compilers, compiler => new Promise((resolve, reject) => {
|
await sequence(this.compiler.compilers, compiler => new Promise((resolve, reject) => {
|
||||||
if (this.options.dev) {
|
if (this.options.dev) {
|
||||||
// --- Dev Build ---
|
// --- Dev Build ---
|
||||||
if (compiler.options.name === 'client') {
|
if (compiler.options.name === 'client') {
|
||||||
// Client watch is started by dev-middleware
|
// Client watch is started by dev-middleware
|
||||||
resolve()
|
resolve()
|
||||||
|
} else if (compiler.options.name.includes('-dll')) {
|
||||||
|
// DLL builds should run once
|
||||||
|
compiler.run((err, stats) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
debug('[DLL] updated')
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// Build and watch for changes
|
// Build and watch for changes
|
||||||
compiler.watch(this.options.watchers.webpack, (err) => {
|
compiler.watch(this.options.watchers.webpack, (err) => {
|
||||||
@ -440,7 +481,7 @@ export default class Builder extends Tapable {
|
|||||||
if (err) return console.error(err) // eslint-disable-line no-console
|
if (err) return console.error(err) // eslint-disable-line no-console
|
||||||
|
|
||||||
// Show build stats for production
|
// Show build stats for production
|
||||||
console.log(stats.toString(this.webpackStats))// eslint-disable-line no-console
|
console.log(stats.toString(this.webpackStats)) // eslint-disable-line no-console
|
||||||
|
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (stats.hasErrors()) {
|
if (stats.hasErrors()) {
|
||||||
|
@ -12,10 +12,11 @@ import { isUrl, urlJoin } from 'utils'
|
|||||||
| webpack config files
|
| webpack config files
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export default function webpackBaseConfig ({ isClient, isServer }) {
|
export default function webpackBaseConfig (name) {
|
||||||
const nodeModulesDir = join(__dirname, '..', 'node_modules')
|
const nodeModulesDir = join(__dirname, '..', 'node_modules')
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
|
name,
|
||||||
devtool: this.options.dev ? 'cheap-module-source-map' : 'nosources-source-map',
|
devtool: this.options.dev ? 'cheap-module-source-map' : 'nosources-source-map',
|
||||||
entry: {
|
entry: {
|
||||||
app: null
|
app: null
|
||||||
@ -63,7 +64,7 @@ export default function webpackBaseConfig ({ isClient, isServer }) {
|
|||||||
{
|
{
|
||||||
test: /\.vue$/,
|
test: /\.vue$/,
|
||||||
loader: 'vue-loader',
|
loader: 'vue-loader',
|
||||||
options: this.vueLoader({ isClient, isServer })
|
options: this.vueLoader()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
|
@ -7,8 +7,13 @@ import ProgressBarPlugin from 'progress-bar-webpack-plugin'
|
|||||||
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
|
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
|
||||||
import MinifyPlugin from 'babel-minify-webpack-plugin'
|
import MinifyPlugin from 'babel-minify-webpack-plugin'
|
||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
|
import { existsSync } from 'fs'
|
||||||
|
import Debug from 'debug'
|
||||||
import base from './base.config.js'
|
import base from './base.config.js'
|
||||||
|
|
||||||
|
const debug = Debug('nuxt:build')
|
||||||
|
debug.color = 2 // Force green color
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Webpack Client Config
|
| Webpack Client Config
|
||||||
@ -20,29 +25,16 @@ import base from './base.config.js'
|
|||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export default function webpackClientConfig () {
|
export default function webpackClientConfig () {
|
||||||
let config = base.call(this, { isClient: true })
|
let config = base.call(this, 'client')
|
||||||
|
|
||||||
config.name = 'client'
|
|
||||||
|
|
||||||
// App entry
|
// App entry
|
||||||
config.entry.app = resolve(this.options.buildDir, 'client.js')
|
config.entry.app = resolve(this.options.buildDir, 'client.js')
|
||||||
|
|
||||||
// Add vendors
|
|
||||||
// This vendors should explicitly extracted
|
|
||||||
// Even if not used in 50% of the chunks!
|
|
||||||
const vendor = [
|
|
||||||
'vue',
|
|
||||||
'vue-router',
|
|
||||||
'vue-meta',
|
|
||||||
'core-js',
|
|
||||||
'regenerator-runtime',
|
|
||||||
'es6-promise',
|
|
||||||
'babel-runtime',
|
|
||||||
'vuex'
|
|
||||||
].concat(this.options.build.vendor).filter(v => v)
|
|
||||||
|
|
||||||
// Extract vendor chunks for better caching
|
// Extract vendor chunks for better caching
|
||||||
const _this = this
|
const _this = this
|
||||||
|
const totalPages = _this.routes ? _this.routes.length : 0
|
||||||
|
const vendor = this.vendor()
|
||||||
|
|
||||||
config.plugins.push(
|
config.plugins.push(
|
||||||
new webpack.optimize.CommonsChunkPlugin({
|
new webpack.optimize.CommonsChunkPlugin({
|
||||||
name: 'common',
|
name: 'common',
|
||||||
@ -56,13 +48,11 @@ export default function webpackClientConfig () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract all explicit vendor modules
|
// Extract all explicit vendor modules
|
||||||
|
// Vendor should explicitly extracted even if not used in 50% of the chunks!
|
||||||
if (module.context && vendor.some(v => module.context.includes(v))) {
|
if (module.context && vendor.some(v => module.context.includes(v))) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total pages
|
|
||||||
const totalPages = _this.routes ? _this.routes.length : 0
|
|
||||||
|
|
||||||
// A module is extracted into the vendor chunk when...
|
// A module is extracted into the vendor chunk when...
|
||||||
return (
|
return (
|
||||||
// If it's inside node_modules
|
// If it's inside node_modules
|
||||||
@ -157,6 +147,27 @@ export default function webpackClientConfig () {
|
|||||||
new webpack.HotModuleReplacementPlugin(),
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
new webpack.NoEmitOnErrorsPlugin()
|
new webpack.NoEmitOnErrorsPlugin()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
debug('[DLL] ' + _dlls.join(','))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
46
lib/builder/webpack/dll.config.js
Normal file
46
lib/builder/webpack/dll.config.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import webpack from 'webpack'
|
||||||
|
import { resolve } from 'path'
|
||||||
|
import ClientConfig from './client.config'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Webpack Dll Config
|
||||||
|
| https://github.com/webpack/webpack/tree/master/examples/dll
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
export default function webpackDllConfig (_refConfig) {
|
||||||
|
const refConfig = _refConfig || new ClientConfig()
|
||||||
|
|
||||||
|
const name = refConfig.name + '-dll'
|
||||||
|
const dllDir = resolve(this.options.cacheDir, name)
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
name,
|
||||||
|
entry: this.vendorEntries(),
|
||||||
|
// context: this.options.rootDir,
|
||||||
|
resolve: refConfig.resolve,
|
||||||
|
target: refConfig.target,
|
||||||
|
resolveLoader: refConfig.resolveLoader,
|
||||||
|
module: refConfig.module,
|
||||||
|
plugins: []
|
||||||
|
}
|
||||||
|
|
||||||
|
config.output = {
|
||||||
|
path: dllDir,
|
||||||
|
filename: '[name]_[hash].js',
|
||||||
|
library: '[name]_[hash]'
|
||||||
|
}
|
||||||
|
|
||||||
|
config.plugins.push(
|
||||||
|
new webpack.DllPlugin({
|
||||||
|
// The path to the manifest file which maps between
|
||||||
|
// modules included in a bundle and the internal IDs
|
||||||
|
// within that bundle
|
||||||
|
path: resolve(dllDir, '[name]-manifest.json'),
|
||||||
|
|
||||||
|
name: '[name]_[hash]'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
@ -12,9 +12,7 @@ import base from './base.config.js'
|
|||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export default function webpackServerConfig () {
|
export default function webpackServerConfig () {
|
||||||
let config = base.call(this, { isServer: true })
|
let config = base.call(this, 'server')
|
||||||
|
|
||||||
config.name = 'server'
|
|
||||||
|
|
||||||
// env object defined in nuxt.config.js
|
// env object defined in nuxt.config.js
|
||||||
let env = {}
|
let env = {}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export default function vueLoader ({ isClient }) {
|
export default function vueLoader () {
|
||||||
// https://vue-loader.vuejs.org/en
|
// https://vue-loader.vuejs.org/en
|
||||||
const config = {
|
const config = {
|
||||||
postcss: this.options.build.postcss,
|
postcss: this.options.build.postcss,
|
||||||
|
@ -33,7 +33,8 @@ Options.from = function (_options) {
|
|||||||
options.rootDir = hasValue(options.rootDir) ? options.rootDir : process.cwd()
|
options.rootDir = hasValue(options.rootDir) ? options.rootDir : process.cwd()
|
||||||
options.srcDir = hasValue(options.srcDir) ? resolve(options.rootDir, options.srcDir) : options.rootDir
|
options.srcDir = hasValue(options.srcDir) ? resolve(options.rootDir, options.srcDir) : options.rootDir
|
||||||
options.modulesDir = resolve(options.rootDir, hasValue(options.modulesDir) ? options.modulesDir : 'node_modules')
|
options.modulesDir = resolve(options.rootDir, hasValue(options.modulesDir) ? options.modulesDir : 'node_modules')
|
||||||
options.buildDir = join(options.rootDir, options.buildDir)
|
options.buildDir = resolve(options.rootDir, options.buildDir)
|
||||||
|
options.cacheDir = resolve(options.rootDir, options.cacheDir)
|
||||||
|
|
||||||
// If app.html is defined, set the template path to the user template
|
// If app.html is defined, set the template path to the user template
|
||||||
options.appTemplatePath = resolve(options.buildDir, 'views/app.template.html')
|
options.appTemplatePath = resolve(options.buildDir, 'views/app.template.html')
|
||||||
@ -162,9 +163,11 @@ Options.defaults = {
|
|||||||
dev: process.env.NODE_ENV !== 'production',
|
dev: process.env.NODE_ENV !== 'production',
|
||||||
debug: undefined, // Will be equal to dev if not provided
|
debug: undefined, // Will be equal to dev if not provided
|
||||||
buildDir: '.nuxt',
|
buildDir: '.nuxt',
|
||||||
|
cacheDir: '.cache',
|
||||||
nuxtAppDir: resolve(__dirname, '../lib/app/'), // Relative to dist
|
nuxtAppDir: resolve(__dirname, '../lib/app/'), // Relative to dist
|
||||||
build: {
|
build: {
|
||||||
analyze: false,
|
analyze: false,
|
||||||
|
dll: false,
|
||||||
extractCSS: false,
|
extractCSS: false,
|
||||||
cssSourceMap: undefined,
|
cssSourceMap: undefined,
|
||||||
ssr: undefined,
|
ssr: undefined,
|
||||||
@ -266,7 +269,9 @@ Options.defaults = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watchers: {
|
watchers: {
|
||||||
webpack: {},
|
webpack: {
|
||||||
|
ignored: /-dll/
|
||||||
|
},
|
||||||
chokidar: {}
|
chokidar: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user