diff --git a/packages/nuxt3/src/builder/builder.ts b/packages/nuxt3/src/builder/builder.ts index 1e2d7e8366..fe2b571075 100644 --- a/packages/nuxt3/src/builder/builder.ts +++ b/packages/nuxt3/src/builder/builder.ts @@ -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() } diff --git a/packages/nuxt3/src/webpack/builder.ts b/packages/nuxt3/src/webpack/builder.ts index 666ccdd6e9..0d636587f3 100644 --- a/packages/nuxt3/src/webpack/builder.ts +++ b/packages/nuxt3/src/webpack/builder.ts @@ -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 + + 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 } } diff --git a/packages/nuxt3/src/webpack/config/base.ts b/packages/nuxt3/src/webpack/config/base.ts index 9aafcbe639..286a467da3 100644 --- a/packages/nuxt3/src/webpack/config/base.ts +++ b/packages/nuxt3/src/webpack/config/base.ts @@ -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 } diff --git a/packages/nuxt3/src/webpack/config/client.ts b/packages/nuxt3/src/webpack/config/client.ts index d04311b07a..f662934a89 100644 --- a/packages/nuxt3/src/webpack/config/client.ts +++ b/packages/nuxt3/src/webpack/config/client.ts @@ -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 diff --git a/packages/nuxt3/src/webpack/config/server.ts b/packages/nuxt3/src/webpack/config/server.ts index 7287913eb4..f8c6de7faa 100644 --- a/packages/nuxt3/src/webpack/config/server.ts +++ b/packages/nuxt3/src/webpack/config/server.ts @@ -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({ diff --git a/packages/nuxt3/src/webpack/utils/perf-loader.ts b/packages/nuxt3/src/webpack/utils/perf-loader.ts index 35f7b349e4..171482dd77 100644 --- a/packages/nuxt3/src/webpack/utils/perf-loader.ts +++ b/packages/nuxt3/src/webpack/utils/perf-loader.ts @@ -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({ diff --git a/packages/nuxt3/src/webpack/utils/postcss.ts b/packages/nuxt3/src/webpack/utils/postcss.ts index 564ba9b2ed..1e734d8699 100644 --- a/packages/nuxt3/src/webpack/utils/postcss.ts +++ b/packages/nuxt3/src/webpack/utils/postcss.ts @@ -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 diff --git a/packages/nuxt3/src/webpack/utils/style-loader.ts b/packages/nuxt3/src/webpack/utils/style-loader.ts index e9f470f3b7..1813781f3d 100644 --- a/packages/nuxt3/src/webpack/utils/style-loader.ts +++ b/packages/nuxt3/src/webpack/utils/style-loader.ts @@ -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(),