refactor(builder): remove buildContext (#25)

This commit is contained in:
Xin Du (Clark) 2020-08-18 21:33:58 +01:00 committed by GitHub
parent d1718230ed
commit f6355ca65d
8 changed files with 108 additions and 94 deletions

View File

@ -81,13 +81,5 @@ export async function generate (builder: Builder) {
}
async function bundle ({ nuxt }: Builder) {
// TODO: get rid of this context and directly pass nuxt to BundleBuilder
const bundleBuilder = new BundleBuilder({
nuxt,
options: nuxt.options,
buildOptions: nuxt.options.build,
target: nuxt.options.target,
plugins: []
})
await bundleBuilder.build()
await new BundleBuilder(nuxt).build()
}

View File

@ -6,6 +6,7 @@ import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import consola from 'consola'
import { Nuxt } from 'src/core'
import { TARGETS, parallel, sequence, wrapArray, isModernRequest } from 'src/utils'
import { createMFS } from './utils/mfs'
@ -15,8 +16,13 @@ import PerfLoader from './utils/perf-loader'
const glob = pify(Glob)
export class WebpackBundler {
constructor (buildContext) {
this.buildContext = buildContext
nuxt: Nuxt
plugins: Array<string>
constructor (nuxt) {
this.nuxt = nuxt
// TODO: plugins
this.plugins = []
// Class fields
this.compilers = []
@ -28,7 +34,7 @@ export class WebpackBundler {
this.middleware = this.middleware.bind(this)
// Initialize shared MFS for dev
if (this.buildContext.options.dev) {
if (this.nuxt.options.dev) {
this.mfs = createMFS()
}
}
@ -43,7 +49,7 @@ export class WebpackBundler {
}
async build () {
const { options } = this.buildContext
const { options } = this.nuxt
const webpackConfigs = [
this.getWebpackConfig('Client')
@ -57,10 +63,10 @@ export class WebpackBundler {
webpackConfigs.push(this.getWebpackConfig('Server'))
}
await this.buildContext.nuxt.callHook('webpack:config', webpackConfigs)
await this.nuxt.callHook('webpack:config', webpackConfigs)
// Check styleResource existence
const { styleResources } = this.buildContext.options.build
const { styleResources } = this.nuxt.options.build
if (styleResources && Object.keys(styleResources).length) {
consola.warn(
'Using styleResources without the @nuxtjs/style-resources is not suggested and can lead to severe performance issues.',
@ -68,7 +74,7 @@ export class WebpackBundler {
)
for (const ext of Object.keys(styleResources)) {
await Promise.all(wrapArray(styleResources[ext]).map(async (p) => {
const styleResourceFiles = await glob(path.resolve(this.buildContext.options.rootDir, p))
const styleResourceFiles = await glob(path.resolve(this.nuxt.options.rootDir, p))
if (!styleResourceFiles || styleResourceFiles.length === 0) {
throw new Error(`Style Resource not found: ${p}`)
@ -104,20 +110,20 @@ export class WebpackBundler {
async webpackCompile (compiler) {
const { name } = compiler.options
const { nuxt, options } = this.buildContext
const { options } = this.nuxt
await nuxt.callHook('build:compile', { name, compiler })
await this.nuxt.callHook('build:compile', { name, compiler })
// Load renderer resources after build
compiler.hooks.done.tap('load-resources', async (stats) => {
await nuxt.callHook('build:compiled', {
await this.nuxt.callHook('build:compiled', {
name,
compiler,
stats
})
// Reload renderer
await nuxt.callHook('build:resources', this.mfs)
await this.nuxt.callHook('build:resources', this.mfs)
})
// --- Dev Build ---
@ -160,14 +166,14 @@ export class WebpackBundler {
}
// Await for renderer to load resources (programmatic, tests and generate)
await nuxt.callHook('build:resources')
await this.nuxt.callHook('build:resources')
}
async webpackDev (compiler) {
consola.debug('Creating webpack middleware...')
const { name } = compiler.options
const buildOptions = this.buildContext.options.build
const buildOptions = this.nuxt.options.build
const { client, ...hotMiddlewareOptions } = buildOptions.hotMiddleware || {}
// Create webpack dev middleware
@ -177,7 +183,7 @@ export class WebpackBundler {
publicPath: buildOptions.publicPath,
stats: false,
logLevel: 'silent',
watchOptions: this.buildContext.options.watchers.webpack,
watchOptions: this.nuxt.options.watchers.webpack,
fs: this.mfs,
...buildOptions.devMiddleware
})
@ -198,11 +204,11 @@ export class WebpackBundler {
)
// Register devMiddleware on server
await this.buildContext.nuxt.callHook('server:devMiddleware', this.middleware)
await this.nuxt.callHook('server:devMiddleware', this.middleware)
}
async middleware (req, res, next) {
const name = isModernRequest(req, this.buildContext.options.modern) ? 'modern' : 'client'
const name = isModernRequest(req, this.nuxt.options.modern) ? 'modern' : 'client'
if (this.devMiddleware && this.devMiddleware[name]) {
await this.devMiddleware[name](req, res)
@ -251,6 +257,6 @@ export class WebpackBundler {
}
forGenerate () {
this.buildContext.target = TARGETS.static
this.nuxt.options.target = TARGETS.static
}
}

View File

@ -10,6 +10,7 @@ import TerserWebpackPlugin from 'terser-webpack-plugin'
import WebpackBar from 'webpackbar'
import env from 'std-env'
import semver from 'semver'
import type { NormalizedConfiguration } from 'src/config'
import { TARGETS, isUrl, urlJoin, getPKG } from 'src/utils'
import PerfLoader from '../utils/perf-loader'
import StyleLoader from '../utils/style-loader'
@ -17,9 +18,11 @@ import WarningIgnorePlugin from '../plugins/warning-ignore'
import { reservedVueTags } from '../utils/reserved-tags'
export default class WebpackBaseConfig {
options: NormalizedConfiguration
constructor (builder) {
this.builder = builder
this.buildContext = builder.buildContext
this.options = builder.nuxt.options
}
get colors () {
@ -49,16 +52,16 @@ export default class WebpackBaseConfig {
}
get target () {
return this.buildContext.target
return this.options.target
}
get dev () {
return this.buildContext.options.dev
return this.options.dev
}
get loaders () {
if (!this._loaders) {
this._loaders = cloneDeep(this.buildContext.buildOptions.loaders)
this._loaders = cloneDeep(this.options.build.loaders)
// sass-loader<8 support (#6460)
const sassLoaderPKG = getPKG('sass-loader')
if (sassLoaderPKG && semver.lt(sassLoaderPKG.version, '8.0.0')) {
@ -80,7 +83,7 @@ export default class WebpackBaseConfig {
normalizeTranspile ({ pathNormalize = false } = {}) {
const transpile = []
for (let pattern of this.buildContext.buildOptions.transpile) {
for (let pattern of this.options.build.transpile) {
if (typeof pattern === 'function') {
pattern = pattern(this.nuxtEnv)
}
@ -99,7 +102,7 @@ export default class WebpackBaseConfig {
getBabelOptions () {
const envName = this.name
const options = {
...this.buildContext.buildOptions.babel,
...this.options.build.babel,
envName
}
@ -136,7 +139,7 @@ export default class WebpackBaseConfig {
}
getFileName (key) {
let fileName = this.buildContext.buildOptions.filenames[key]
let fileName = this.options.build.filenames[key]
if (typeof fileName === 'function') {
fileName = fileName(this.nuxtEnv)
}
@ -158,13 +161,13 @@ export default class WebpackBaseConfig {
'process.static': this.target === TARGETS.static,
'process.target': JSON.stringify(this.target)
}
if (this.buildContext.buildOptions.aggressiveCodeRemoval) {
if (this.options.build.aggressiveCodeRemoval) {
env['typeof process'] = JSON.stringify(this.isServer ? 'object' : 'undefined')
env['typeof window'] = JSON.stringify(!this.isServer ? 'object' : 'undefined')
env['typeof document'] = JSON.stringify(!this.isServer ? 'object' : 'undefined')
}
Object.entries(this.buildContext.options.env).forEach(([key, value]) => {
Object.entries(this.options.env).forEach(([key, value]) => {
env['process.env.' + key] =
['boolean', 'number'].includes(typeof value)
? value
@ -175,9 +178,10 @@ export default class WebpackBaseConfig {
output () {
const {
options: { buildDir, router },
buildOptions: { publicPath }
} = this.buildContext
build: { publicPath },
buildDir,
router
} = this.options
return {
path: path.resolve(buildDir, 'dist', this.isServer ? 'server' : 'client'),
filename: this.getFileName('app'),
@ -187,7 +191,7 @@ export default class WebpackBaseConfig {
}
cache () {
if (!this.buildContext.buildOptions.cache) {
if (!this.options.build.cache) {
return false
}
@ -195,15 +199,15 @@ export default class WebpackBaseConfig {
type: 'filesystem',
cacheDirectory: path.resolve('node_modules/.cache/@nuxt/webpack/'),
buildDependencies: {
config: [...this.buildContext.options._nuxtConfigFiles]
config: [...this.options._nuxtConfigFiles]
},
...this.buildContext.buildOptions.cache,
...this.options.build.cache,
name: this.name
}
}
optimization () {
const optimization = cloneDeep(this.buildContext.buildOptions.optimization)
const optimization = cloneDeep(this.options.build.optimization)
if (optimization.minimize && optimization.minimizer === undefined) {
optimization.minimizer = this.minimizer()
@ -214,7 +218,7 @@ export default class WebpackBaseConfig {
resolve () {
// Prioritize nested node_modules in webpack search path (#2558)
const webpackModulesDir = ['node_modules'].concat(this.buildContext.options.modulesDir)
const webpackModulesDir = ['node_modules'].concat(this.options.modulesDir)
return {
resolve: {
@ -230,7 +234,7 @@ export default class WebpackBaseConfig {
minimizer () {
const minimizer = []
const { terser, cache } = this.buildContext.buildOptions
const { terser, cache } = this.options.build
// https://github.com/webpack-contrib/terser-webpack-plugin
if (terser) {
@ -258,17 +262,17 @@ export default class WebpackBaseConfig {
alias () {
return {
...this.buildContext.options.alias,
app: this.buildContext.options.appDir,
'nuxt-build': this.buildContext.options.buildDir,
...this.options.alias,
app: this.options.appDir,
'nuxt-build': this.options.buildDir,
'vue-meta': require.resolve(`vue-meta${this.isServer ? '' : '/dist/vue-meta.esm.browser.js'}`)
}
}
rules () {
const perfLoader = new PerfLoader(this.name, this.buildContext)
const perfLoader = new PerfLoader(this.name, this.options)
const styleLoader = new StyleLoader(
this.buildContext,
this.builder.nuxt,
{ isServer: this.isServer, perfLoader }
)
@ -390,7 +394,8 @@ export default class WebpackBaseConfig {
plugins () {
const plugins = []
const { nuxt, buildOptions } = this.buildContext
const { nuxt } = this.builder
const { build: buildOptions } = this.options
// Add timefix-plugin before others plugins
if (this.dev) {
@ -431,8 +436,8 @@ export default class WebpackBaseConfig {
nuxt.callHook('bundler:change', shortPath)
}
},
done: (buildContext) => {
if (buildContext.hasErrors) {
done: (stats) => {
if (stats.hasErrors) {
nuxt.callHook('bundler:error')
}
},
@ -446,13 +451,13 @@ export default class WebpackBaseConfig {
}))
// CSS extraction
if (this.buildContext.buildOptions.extractCSS) {
if (this.options.build.extractCSS) {
plugins.push(new MiniCssExtractPlugin(Object.assign({
filename: this.getFileName('css'),
chunkFilename: this.getFileName('css'),
// TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132
reloadAll: true
}, this.buildContext.buildOptions.extractCSS)))
}, this.options.build.extractCSS)))
}
return plugins
@ -464,14 +469,14 @@ export default class WebpackBaseConfig {
warn => warn.name === 'ModuleDependencyWarning' &&
warn.message.includes('export \'default\'') &&
warn.message.includes('nuxt_plugin_'),
...(this.buildContext.buildOptions.warningIgnoreFilters || [])
...(this.options.build.warningIgnoreFilters || [])
]
return warn => !filters.some(ignoreFilter => ignoreFilter(warn))
}
extendConfig (config) {
const { extend } = this.buildContext.buildOptions
const { extend } = this.options.build
if (typeof extend === 'function') {
const extendedConfig = extend.call(
this.builder, config, { loaders: this.loaders, ...this.nuxtEnv }

View File

@ -31,8 +31,8 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
}
getCspScriptPolicy () {
const { csp } = this.buildContext.options.render
if (csp) {
const { csp } = this.options.render
if (typeof csp === 'object') {
const { policies = {} } = csp
return policies['script-src'] || policies['default-src'] || []
}
@ -59,7 +59,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
// Small, known and common modules which are usually used project-wise
// Sum of them may not be more than 244 KiB
if (
this.buildContext.buildOptions.splitChunks.commons === true &&
this.options.build.splitChunks.commons === true &&
cacheGroups.commons === undefined
) {
cacheGroups.commons = {
@ -89,7 +89,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
minimizer () {
const minimizer = super.minimizer()
const { optimizeCSS } = this.buildContext.buildOptions
const { optimizeCSS } = this.options.build
// https://github.com/NMFR/optimize-css-assets-webpack-plugin
// https://github.com/webpack-contrib/mini-css-extract-plugin#minimizing-for-production
@ -104,7 +104,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
alias () {
const aliases = super.alias()
for (const p of this.buildContext.plugins) {
for (const p of this.builder.plugins) {
if (!aliases[p.name]) {
// Do not load server-side plugins on client-side
aliases[p.name] = p.mode === 'server' ? './empty.js' : p.src
@ -116,7 +116,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
plugins () {
const plugins = super.plugins()
const { buildOptions, options: { appTemplatePath, buildDir, modern, render } } = this.buildContext
const { build: buildOptions, appTemplatePath, buildDir, modern, render } = this.options
// Generate output HTML for SSR
if (buildOptions.ssr) {
@ -185,9 +185,10 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
config () {
const config = super.config()
const {
options: { router, buildDir },
buildOptions: { hotMiddleware, quiet, friendlyErrors }
} = this.buildContext
router,
buildDir,
build: { hotMiddleware, quiet, friendlyErrors }
} = this.options
const { client = {} } = hotMiddleware || {}
const { ansiColors, overlayStyles, ...options } = client

View File

@ -59,7 +59,7 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
}
optimization () {
const { _minifyServer } = this.buildContext.buildOptions
const { _minifyServer } = this.options.build
return {
splitChunks: false,
@ -78,7 +78,7 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
alias () {
const aliases = super.alias()
for (const p of this.buildContext.plugins) {
for (const p of this.builder.plugins) {
if (!aliases[p.name]) {
// Do not load client-side plugins on server-side
aliases[p.name] = p.mode === 'client' ? './empty.js' : p.src
@ -95,7 +95,7 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
new DefinePlugin(this.env())
)
const { serverURLPolyfill } = this.buildContext.options.build
const { serverURLPolyfill } = this.options.build
if (serverURLPolyfill) {
plugins.push(new ProvidePlugin({
@ -114,7 +114,7 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
target: 'node',
node: false,
entry: Object.assign({}, config.entry, {
app: [path.resolve(this.buildContext.options.buildDir, 'entry.server.ts')]
app: [path.resolve(this.options.buildDir, 'entry.server.ts')]
}),
output: Object.assign({}, config.output, {
filename: 'server.js',
@ -132,8 +132,8 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
// https://webpack.js.org/configuration/externals/#externals
// https://github.com/liady/webpack-node-externals
// https://vue-loader.vuejs.org/migrating.html#ssr-externals
if (!this.buildContext.buildOptions.standalone) {
this.buildContext.options.modulesDir.forEach((dir) => {
if (!this.options.build.standalone) {
this.options.modulesDir.forEach((dir) => {
if (fs.existsSync(dir)) {
config.externals.push(
nodeExternals({

View File

@ -3,10 +3,10 @@ import { warmup } from 'thread-loader'
// https://github.com/webpack-contrib/thread-loader
export default class PerfLoader {
constructor (name, buildContext) {
constructor (name, options) {
this.name = name
this.buildContext = buildContext
this.workerPools = PerfLoader.defaultPools({ dev: buildContext.options.dev })
this.options = options
this.workerPools = PerfLoader.defaultPools({ dev: options.dev })
return new Proxy(this, {
get (target, name) {
return target[name] ? target[name] : target.use.bind(target, name)
@ -38,7 +38,7 @@ export default class PerfLoader {
use (poolName) {
const loaders = []
if (this.buildContext.buildOptions) {
if (this.options.build.buildOptions) {
const pool = this.workerPools[poolName]
if (pool) {
loaders.push({

View File

@ -6,6 +6,8 @@ import merge from 'lodash/merge'
import cloneDeep from 'lodash/cloneDeep'
import createResolver from 'postcss-import-resolver'
import type { Nuxt } from 'src/core'
import type { NormalizedConfiguration } from 'src/config'
import { isPureObject } from 'src/utils'
export const orderPresets = {
@ -37,16 +39,20 @@ function postcssConfigFileWarning () {
}
export default class PostcssConfig {
constructor (buildContext) {
this.buildContext = buildContext
nuxt: Nuxt
options: NormalizedConfiguration
constructor (nuxt) {
this.nuxt = nuxt
this.options = nuxt.options
}
get postcssOptions () {
return this.buildContext.buildOptions.postcss
return this.options.build.postcss
}
get postcssImportAlias () {
const alias = { ...this.buildContext.options.alias }
const alias = { ...this.options.alias }
for (const key in alias) {
if (key.startsWith('~')) {
@ -62,9 +68,9 @@ export default class PostcssConfig {
}
get defaultConfig () {
const { dev, srcDir, rootDir, modulesDir } = this.buildContext.options
const { dev, srcDir, rootDir, modulesDir } = this.options
return {
sourceMap: this.buildContext.buildOptions.cssSourceMap,
sourceMap: this.options.build.cssSourceMap,
plugins: {
// https://github.com/postcss/postcss-import
'postcss-import': {
@ -90,7 +96,7 @@ export default class PostcssConfig {
// Search for postCSS config file and use it if exists
// https://github.com/michael-ciniawsky/postcss-load-config
// TODO: Remove in Nuxt 3
const { srcDir, rootDir } = this.buildContext.options
const { srcDir, rootDir } = this.options
for (const dir of [srcDir, rootDir]) {
for (const file of [
'postcss.config.js',
@ -114,7 +120,7 @@ export default class PostcssConfig {
if (loaderConfig.path) {
return {
sourceMap: this.buildContext.buildOptions.cssSourceMap,
sourceMap: this.options.build.cssSourceMap,
config: loaderConfig
}
}
@ -144,7 +150,7 @@ export default class PostcssConfig {
// Map postcss plugins into instances on object mode once
config.plugins = this.sortPlugins(config)
.map((p) => {
const plugin = this.buildContext.nuxt.resolver.requireModule(p)
const plugin = this.nuxt.resolver.requireModule(p)
const opts = plugins[p]
if (opts === false) {
return // Disabled

View File

@ -2,23 +2,27 @@ import path from 'path'
// import ExtractCssChunksPlugin from 'extract-css-chunks-webpack-plugin'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import type { Nuxt } from 'src/core'
import type { NormalizedConfiguration } from 'src/config'
import { wrapArray } from 'src/utils'
import PostcssConfig from './postcss'
export default class StyleLoader {
constructor (buildContext, { isServer, perfLoader }) {
this.buildContext = buildContext
options: NormalizedConfiguration
constructor (nuxt: Nuxt, { isServer, perfLoader }) {
this.options = nuxt.options
this.isServer = isServer
this.perfLoader = perfLoader
if (buildContext.options.build.postcss) {
this.postcssConfig = new PostcssConfig(buildContext)
if (this.options.build.postcss) {
this.postcssConfig = new PostcssConfig(nuxt)
}
}
get extractCSS () {
return this.buildContext.buildOptions.extractCSS
return this.options.build.extractCSS
}
get onlyLocals () {
@ -32,7 +36,7 @@ export default class StyleLoader {
}
styleResource (ext) {
const { buildOptions: { styleResources }, options: { rootDir } } = this.buildContext
const { build: { styleResources }, rootDir } = this.options
const extResource = styleResources[ext]
// style-resources-loader
// https://github.com/yenshih/style-resources-loader
@ -65,7 +69,7 @@ export default class StyleLoader {
return {
loader: 'postcss-loader',
options: Object.assign({ sourceMap: this.buildContext.buildOptions.cssSourceMap }, config)
options: Object.assign({ sourceMap: this.options.build.cssSourceMap }, config)
}
}
@ -86,7 +90,7 @@ export default class StyleLoader {
extract () {
if (this.extractCSS) {
const isDev = this.buildContext.options.dev
const isDev = this.options.dev
return {
loader: MiniCssExtractPlugin.loader,
options: {
@ -102,12 +106,12 @@ export default class StyleLoader {
styleLoader () {
return this.extract() || {
loader: 'vue-style-loader',
options: this.buildContext.buildOptions.loaders.vueStyle
options: this.options.build.loaders.vueStyle
}
}
apply (ext, loaders = []) {
const { css, cssModules } = this.buildContext.buildOptions.loaders
const { css, cssModules } = this.options.build.loaders
const customLoaders = [].concat(
this.postcss(),