refactor: perf loader (#4299)

This commit is contained in:
Clark Du 2018-11-08 22:26:52 +00:00 committed by GitHub
parent 57f66726d0
commit 2c4bd57101
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 74 deletions

View File

@ -26,7 +26,6 @@ export class WebpackBundler {
this.compilersWatching = [] this.compilersWatching = []
this.devMiddleware = {} this.devMiddleware = {}
this.hotMiddleware = {} this.hotMiddleware = {}
this.perfLoader = null
// Initialize shared FS and Cache // Initialize shared FS and Cache
if (this.context.options.dev) { if (this.context.options.dev) {
@ -37,8 +36,6 @@ export class WebpackBundler {
async build() { async build() {
const options = this.context.options const options = this.context.options
this.perfLoader = new PerfLoader(options)
const compilersOptions = [] const compilersOptions = []
// Client // Client
@ -104,7 +101,7 @@ export class WebpackBundler {
// Warmup perfLoader before build // Warmup perfLoader before build
if (options.build.parallel) { if (options.build.parallel) {
consola.info('Warming up worker pools') consola.info('Warming up worker pools')
this.perfLoader.warmupAll() PerfLoader.warmupAll({ dev: options.dev })
consola.success('Worker pools ready') consola.success('Worker pools ready')
} }

View File

@ -10,6 +10,7 @@ import env from 'std-env'
import { isUrl, urlJoin } from '@nuxt/common' import { isUrl, urlJoin } from '@nuxt/common'
import PerfLoader from './utils/perf-loader'
import StyleLoader from './utils/style-loader' import StyleLoader from './utils/style-loader'
import WarnFixPlugin from './plugins/warnfix' import WarnFixPlugin from './plugins/warnfix'
@ -125,14 +126,13 @@ export default class WebpackBaseConfig {
} }
rules() { rules() {
const perfLoader = new PerfLoader(this)
const styleLoader = new StyleLoader( const styleLoader = new StyleLoader(
this.options, this.options,
this.nuxt, this.nuxt,
{ isServer: this.isServer } { isServer: this.isServer, perfLoader }
) )
const perfLoader = this.builder.perfLoader
return [ return [
{ {
test: /\.vue$/, test: /\.vue$/,
@ -173,46 +173,46 @@ export default class WebpackBaseConfig {
return !modulesToTranspile.some(module => module.test(file)) return !modulesToTranspile.some(module => module.test(file))
}, },
use: perfLoader.pool('js', { use: perfLoader.js().concat({
loader: require.resolve('babel-loader'), loader: require.resolve('babel-loader'),
options: this.getBabelOptions() options: this.getBabelOptions()
}) })
}, },
{ {
test: /\.css$/, test: /\.css$/,
oneOf: perfLoader.poolOneOf('css', styleLoader.apply('css')) oneOf: styleLoader.apply('css')
}, },
{ {
test: /\.less$/, test: /\.less$/,
oneOf: perfLoader.poolOneOf('css', styleLoader.apply('less', { oneOf: styleLoader.apply('less', {
loader: 'less-loader', loader: 'less-loader',
options: this.loaders.less options: this.loaders.less
})) })
}, },
{ {
test: /\.sass$/, test: /\.sass$/,
oneOf: perfLoader.poolOneOf('css', styleLoader.apply('sass', { oneOf: styleLoader.apply('sass', {
loader: 'sass-loader', loader: 'sass-loader',
options: this.loaders.sass options: this.loaders.sass
})) })
}, },
{ {
test: /\.scss$/, test: /\.scss$/,
oneOf: perfLoader.poolOneOf('css', styleLoader.apply('scss', { oneOf: styleLoader.apply('scss', {
loader: 'sass-loader', loader: 'sass-loader',
options: this.loaders.scss options: this.loaders.scss
})) })
}, },
{ {
test: /\.styl(us)?$/, test: /\.styl(us)?$/,
oneOf: perfLoader.poolOneOf('css', styleLoader.apply('stylus', { oneOf: styleLoader.apply('stylus', {
loader: 'stylus-loader', loader: 'stylus-loader',
options: this.loaders.stylus options: this.loaders.stylus
})) })
}, },
{ {
test: /\.(png|jpe?g|gif|svg|webp)$/, test: /\.(png|jpe?g|gif|svg|webp)$/,
use: perfLoader.pool('assets', { use: perfLoader.asset().concat({
loader: 'url-loader', loader: 'url-loader',
options: Object.assign( options: Object.assign(
this.loaders.imgUrl, this.loaders.imgUrl,
@ -222,7 +222,7 @@ export default class WebpackBaseConfig {
}, },
{ {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: perfLoader.pool('assets', { use: perfLoader.asset().concat({
loader: 'url-loader', loader: 'url-loader',
options: Object.assign( options: Object.assign(
this.loaders.fontUrl, this.loaders.fontUrl,
@ -232,7 +232,7 @@ export default class WebpackBaseConfig {
}, },
{ {
test: /\.(webm|mp4|ogv)$/, test: /\.(webm|mp4|ogv)$/,
use: perfLoader.pool('assets', { use: perfLoader.asset().concat({
loader: 'file-loader', loader: 'file-loader',
options: Object.assign( options: Object.assign(
this.loaders.file, this.loaders.file,

View File

@ -6,58 +6,58 @@ import { warmup } from 'thread-loader'
// https://github.com/webpack-contrib/cache-loader // https://github.com/webpack-contrib/cache-loader
export default class PerfLoader { export default class PerfLoader {
constructor(options) { constructor(config) {
this.options = options this.name = config.name
this.warmup = warmup this.options = config.options
this.workerPools = { this.workerPools = PerfLoader.defaultPools(this.options)
js: { return new Proxy(this, {
name: 'js', get(target, name) {
poolTimeout: this.options.dev ? Infinity : 2000 return target[name] ? target[name] : target.use.bind(target, name)
},
css: {
name: 'css',
poolTimeout: this.options.dev ? Infinity : 2000
} }
})
}
static defaultPools({ dev }) {
const poolTimeout = dev ? Infinity : 2000
return {
js: { name: 'js', poolTimeout },
css: { name: 'css', poolTimeout }
} }
} }
warmupAll() { static warmupAll(options) {
this.warmup(this.workerPools.js, [ options = PerfLoader.defaultPools(options)
PerfLoader.warmup(options.js, [
require.resolve('babel-loader'), require.resolve('babel-loader'),
require.resolve('@babel/preset-env') require.resolve('@babel/preset-env')
]) ])
this.warmup(this.workerPools.css, ['css-loader']) PerfLoader.warmup(options.css, ['css-loader'])
} }
pool(poolName, _loaders) { use(poolName) {
const loaders = [].concat(_loaders) const loaders = []
if (this.options.build.cache) {
loaders.push({
loader: 'cache-loader',
options: {
cacheDirectory: path.resolve(`node_modules/.cache/cache-loader/${this.name}`)
}
})
}
if (this.options.build.parallel) { if (this.options.build.parallel) {
const pool = this.workerPools[poolName] const pool = this.workerPools[poolName]
if (pool) { if (pool) {
loaders.unshift({ loaders.push({
loader: 'thread-loader', loader: 'thread-loader',
options: pool options: pool
}) })
} }
} }
if (this.options.build.cache) {
loaders.unshift({
loader: 'cache-loader',
options: {
cacheDirectory: path.resolve('node_modules/.cache/cache-loader')
}
})
}
return loaders return loaders
} }
}
poolOneOf(poolName, oneOfRules) { PerfLoader.warmup = warmup
return oneOfRules.map(rule => Object.assign({}, rule, {
use: this.pool(poolName, rule.use)
}))
}
}

View File

@ -6,8 +6,9 @@ import { wrapArray } from '@nuxt/common'
import PostcssConfig from './postcss' import PostcssConfig from './postcss'
export default class StyleLoader { export default class StyleLoader {
constructor(options, nuxt, { isServer }) { constructor(options, nuxt, { isServer, perfLoader }) {
this.isServer = isServer this.isServer = isServer
this.perfLoader = perfLoader
this.dev = options.dev this.dev = options.dev
this.srcDir = options.srcDir this.srcDir = options.srcDir
this.assetsDir = options.dir.assets this.assetsDir = options.dir.assets
@ -104,7 +105,7 @@ export default class StyleLoader {
// This matches <style module> // This matches <style module>
{ {
resourceQuery: /module/, resourceQuery: /module/,
use: [].concat( use: this.perfLoader.css().concat(
styleLoader, styleLoader,
this.cssModules(cssModulesOptions), this.cssModules(cssModulesOptions),
customLoaders customLoaders
@ -112,7 +113,7 @@ export default class StyleLoader {
}, },
// This matches plain <style> or <style scoped> // This matches plain <style> or <style scoped>
{ {
use: [].concat( use: this.perfLoader.css().concat(
styleLoader, styleLoader,
this.css(cssOptions), this.css(cssOptions),
customLoaders customLoaders

View File

@ -4,32 +4,33 @@ import PerfLoader from '../../packages/webpack/src/config/utils/perf-loader'
describe('webpack configuration', () => { describe('webpack configuration', () => {
test('performance loader', () => { test('performance loader', () => {
const js = { name: 'js', poolTimeout: Infinity }
const css = { name: 'css', poolTimeout: Infinity }
PerfLoader.warmup = jest.fn()
PerfLoader.warmupAll({ dev: true })
expect(PerfLoader.warmup).toHaveBeenCalledTimes(2)
expect(PerfLoader.warmup).toHaveBeenCalledWith(js, [
require.resolve('babel-loader'),
require.resolve('@babel/preset-env')
])
expect(PerfLoader.warmup).toHaveBeenCalledWith(css, ['css-loader'])
const perfLoader = new PerfLoader({ const perfLoader = new PerfLoader({
name: 'test-perf',
options: {
dev: true, dev: true,
build: { build: {
parallel: true, parallel: true,
cache: true cache: true
} }
}
}) })
const js = { name: 'js', poolTimeout: Infinity }
const css = { name: 'css', poolTimeout: Infinity }
expect(perfLoader.workerPools).toMatchObject({ js, css }) expect(perfLoader.workerPools).toMatchObject({ js, css })
const loaders = perfLoader.use('js')
perfLoader.warmup = jest.fn() const cacheDirectory = path.resolve('node_modules/.cache/cache-loader/test-perf')
perfLoader.warmupAll()
expect(perfLoader.warmup).toHaveBeenCalledTimes(2)
expect(perfLoader.warmup).toHaveBeenCalledWith(js, [
require.resolve('babel-loader'),
require.resolve('@babel/preset-env')
])
expect(perfLoader.warmup).toHaveBeenCalledWith(css, ['css-loader'])
const loaders = perfLoader.pool('js', { loader: 'test-perf-loader' })
const cacheDirectory = path.resolve('node_modules/.cache/cache-loader')
expect(loaders).toMatchObject([ expect(loaders).toMatchObject([
{ loader: 'cache-loader', options: { cacheDirectory } }, { loader: 'cache-loader', options: { cacheDirectory } },
{ loader: 'thread-loader', options: js }, { loader: 'thread-loader', options: js }
{ loader: 'test-perf-loader' }
]) ])
}) })
}) })