Skip to content

Commit

Permalink
refactor: unify context in webpack module (#5054)
Browse files Browse the repository at this point in the history
  • Loading branch information
clarkdo committed Feb 18, 2019
1 parent 3ed9f3e commit 9860eb6
Show file tree
Hide file tree
Showing 12 changed files with 194 additions and 163 deletions.
4 changes: 4 additions & 0 deletions packages/builder/src/context/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ export default class BuildContext {
this.isStatic = false
}

get buildOptions() {
return this.options.build
}

get plugins() {
return this._builder.plugins
}
Expand Down
10 changes: 10 additions & 0 deletions packages/builder/test/context/build.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,14 @@ describe('builder: buildContext', () => {
const context = new BuildContext(builder)
expect(context.plugins).toEqual(builder.plugins)
})

test('should return builder build options', () => {
const buildOptions = { id: 'test-build-options' }
const builder = {
plugins: [],
nuxt: { options: { build: buildOptions } }
}
const context = new BuildContext(builder)
expect(context.buildOptions).toEqual(buildOptions)
})
})
20 changes: 10 additions & 10 deletions packages/webpack/src/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ import PerfLoader from './utils/perf-loader'
const glob = pify(Glob)

export class WebpackBundler {
constructor(context) {
this.context = context
constructor(buildContext) {
this.buildContext = buildContext
// Fields that set on build
this.compilers = []
this.compilersWatching = []
this.devMiddleware = {}
this.hotMiddleware = {}

// Initialize shared MFS for dev
if (this.context.options.dev) {
if (this.buildContext.options.dev) {
this.mfs = new MFS()

// TODO: Enable when async FS required
Expand All @@ -38,7 +38,7 @@ export class WebpackBundler {
}

async build() {
const { options } = this.context
const { options } = this.buildContext

const compilersOptions = []

Expand All @@ -60,7 +60,7 @@ export class WebpackBundler {
compilersOptions.push(serverConfig)
}

for (const p of this.context.plugins) {
for (const p of this.buildContext.plugins) {
// Client config
if (!clientConfig.resolve.alias[p.name]) {
clientConfig.resolve.alias[p.name] = p.mode === 'server' ? './empty.js' : p.src
Expand All @@ -78,15 +78,15 @@ export class WebpackBundler {
}

// Check styleResource existence
const { styleResources } = this.context.options.build
const { styleResources } = this.buildContext.options.build
if (styleResources && Object.keys(styleResources).length) {
consola.warn(
'Using styleResources without the nuxt-style-resources-module is not suggested and can lead to severe performance issues.',
'Please use https://github.com/nuxt-community/style-resources-module'
)
for (const ext of Object.keys(styleResources)) {
await Promise.all(wrapArray(styleResources[ext]).map(async (p) => {
const styleResourceFiles = await glob(path.resolve(this.context.options.rootDir, p))
const styleResourceFiles = await glob(path.resolve(this.buildContext.options.rootDir, p))

if (!styleResourceFiles || styleResourceFiles.length === 0) {
throw new Error(`Style Resource not found: ${p}`)
Expand Down Expand Up @@ -122,7 +122,7 @@ export class WebpackBundler {

async webpackCompile(compiler) {
const { name } = compiler.options
const { nuxt, options } = this.context
const { nuxt, options } = this.buildContext

await nuxt.callHook('build:compile', { name, compiler })

Expand Down Expand Up @@ -179,7 +179,7 @@ export class WebpackBundler {
consola.debug('Adding webpack middleware...')

const { name } = compiler.options
const { nuxt: { server }, options } = this.context
const { nuxt: { server }, options } = this.buildContext
const { client, ...hotMiddlewareOptions } = options.build.hotMiddleware || {}

// Create webpack dev middleware
Expand Down Expand Up @@ -255,6 +255,6 @@ export class WebpackBundler {
}

forGenerate() {
this.context.isStatic = true
this.buildContext.isStatic = true
}
}
109 changes: 59 additions & 50 deletions packages/webpack/src/config/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,9 @@ import WarnFixPlugin from '../plugins/warnfix'
import { reservedVueTags } from '../utils/reserved-tags'

export default class WebpackBaseConfig {
constructor(builder, options) {
this.name = options.name
this.isServer = options.isServer
this.isModern = options.isModern
constructor(builder) {
this.builder = builder
this.nuxt = builder.context.nuxt
this.isStatic = builder.context.isStatic
this.options = builder.context.options
this.loaders = this.options.build.loaders
this.buildMode = this.options.dev ? 'development' : 'production'
this.buildContext = builder.buildContext
this.modulesToTranspile = this.normalizeTranspile()
}

Expand All @@ -43,17 +36,29 @@ export default class WebpackBaseConfig {

get nuxtEnv() {
return {
isDev: this.options.dev,
isDev: this.dev,
isServer: this.isServer,
isClient: !this.isServer,
isModern: !!this.isModern
}
}

get mode() {
return this.dev ? 'development' : 'production'
}

get dev() {
return this.buildContext.options.dev
}

get loaders() {
return this.buildContext.buildOptions.loaders
}

normalizeTranspile() {
// include SFCs in node_modules
const items = [/\.vue\.js/i]
for (const pattern of this.options.build.transpile) {
for (const pattern of this.buildContext.buildOptions.transpile) {
if (pattern instanceof RegExp) {
items.push(pattern)
} else {
Expand All @@ -65,7 +70,7 @@ export default class WebpackBaseConfig {
}

getBabelOptions() {
const options = clone(this.options.build.babel)
const options = clone(this.buildContext.buildOptions.babel)

if (typeof options.presets === 'function') {
options.presets = options.presets({ isServer: this.isServer })
Expand All @@ -86,11 +91,11 @@ export default class WebpackBaseConfig {
}

getFileName(key) {
let fileName = this.options.build.filenames[key]
let fileName = this.buildContext.buildOptions.filenames[key]
if (typeof fileName === 'function') {
fileName = fileName(this.nuxtEnv)
}
if (this.options.dev) {
if (this.dev) {
const hash = /\[(chunkhash|contenthash|hash)(?::(\d+))?]/.exec(fileName)
if (hash) {
consola.warn(`Notice: Please do not use ${hash[1]} in dev mode to prevent memory leak`)
Expand All @@ -105,11 +110,11 @@ export default class WebpackBaseConfig {

env() {
const env = {
'process.env.NODE_ENV': JSON.stringify(this.buildMode),
'process.mode': JSON.stringify(this.options.mode),
'process.static': this.isStatic
'process.env.NODE_ENV': JSON.stringify(this.mode),
'process.mode': JSON.stringify(this.mode),
'process.static': this.buildContext.isStatic
}
Object.entries(this.options.env).forEach(([key, value]) => {
Object.entries(this.buildContext.options.env).forEach(([key, value]) => {
env['process.env.' + key] =
['boolean', 'number'].includes(typeof value)
? value
Expand All @@ -119,19 +124,21 @@ export default class WebpackBaseConfig {
}

output() {
const {
options: { buildDir, router },
buildOptions: { publicPath }
} = this.buildContext
return {
path: path.resolve(this.options.buildDir, 'dist', this.isServer ? 'server' : 'client'),
path: path.resolve(buildDir, 'dist', this.isServer ? 'server' : 'client'),
filename: this.getFileName('app'),
futureEmitAssets: true, // TODO: Remove when using webpack 5
chunkFilename: this.getFileName('chunk'),
publicPath: isUrl(this.options.build.publicPath)
? this.options.build.publicPath
: urlJoin(this.options.router.base, this.options.build.publicPath)
publicPath: isUrl(publicPath) ? publicPath : urlJoin(router.base, publicPath)
}
}

optimization() {
const optimization = cloneDeep(this.options.build.optimization)
const optimization = cloneDeep(this.buildContext.buildOptions.optimization)

if (optimization.minimize && optimization.minimizer === undefined) {
optimization.minimizer = this.minimizer()
Expand All @@ -142,13 +149,14 @@ export default class WebpackBaseConfig {

minimizer() {
const minimizer = []
const { terser, cache } = this.buildContext.buildOptions

// https://github.com/webpack-contrib/terser-webpack-plugin
if (this.options.build.terser) {
if (terser) {
minimizer.push(
new TerserWebpackPlugin(Object.assign({
parallel: true,
cache: this.options.build.cache,
cache,
sourceMap: this.devtool && /source-?map/.test(this.devtool),
extractComments: {
filename: 'LICENSES'
Expand All @@ -164,15 +172,15 @@ export default class WebpackBaseConfig {
reserved: reservedVueTags
}
}
}, this.options.build.terser))
}, terser))
)
}

return minimizer
}

alias() {
const { srcDir, rootDir, dir: { assets: assetsDir, static: staticDir } } = this.options
const { srcDir, rootDir, dir: { assets: assetsDir, static: staticDir } } = this.buildContext.options

return {
'~': path.join(srcDir),
Expand All @@ -185,10 +193,9 @@ export default class WebpackBaseConfig {
}

rules() {
const perfLoader = new PerfLoader(this)
const perfLoader = new PerfLoader(this.name, this.buildContext)
const styleLoader = new StyleLoader(
this.options,
this.nuxt,
this.buildContext,
{ isServer: this.isServer, perfLoader }
)
const babelLoader = {
Expand Down Expand Up @@ -329,25 +336,26 @@ export default class WebpackBaseConfig {

plugins() {
const plugins = []
const { nuxt, buildOptions } = this.buildContext

// Add timefix-plugin before others plugins
if (this.options.dev) {
if (this.dev) {
plugins.push(new TimeFixPlugin())
}

// CSS extraction)
if (this.options.build.extractCSS) {
if (buildOptions.extractCSS) {
plugins.push(new ExtractCssChunksPlugin(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.options.build.extractCSS)))
}, buildOptions.extractCSS)))
}

plugins.push(new VueLoader.VueLoaderPlugin())

plugins.push(...(this.options.build.plugins || []))
plugins.push(...(buildOptions.plugins || []))

// Hide warnings about plugins without a default export (#1179)
plugins.push(new WarnFixPlugin())
Expand All @@ -362,37 +370,38 @@ export default class WebpackBaseConfig {
'profile',
'stats'
],
basic: !this.options.build.quiet && env.minimalCLI,
fancy: !this.options.build.quiet && !env.minimalCLI,
profile: !this.options.build.quiet && this.options.build.profile,
stats: !this.options.build.quiet && !this.options.dev && this.options.build.stats,
basic: !buildOptions.quiet && env.minimalCLI,
fancy: !buildOptions.quiet && !env.minimalCLI,
profile: !buildOptions.quiet && buildOptions.profile,
stats: !buildOptions.quiet && !this.dev && buildOptions.stats,
reporter: {
change: (_, { shortPath }) => {
if (!this.isServer) {
this.nuxt.callHook('bundler:change', shortPath)
nuxt.callHook('bundler:change', shortPath)
}
},
done: (context) => {
if (context.hasErrors) {
this.nuxt.callHook('bundler:error')
done: (buildContext) => {
if (buildContext.hasErrors) {
nuxt.callHook('bundler:error')
}
},
allDone: () => {
this.nuxt.callHook('bundler:done')
nuxt.callHook('bundler:done')
}
}
}))

if (this.options.build.hardSource) {
plugins.push(new HardSourcePlugin(Object.assign({}, this.options.build.hardSource)))
if (buildOptions.hardSource) {
plugins.push(new HardSourcePlugin(Object.assign({}, buildOptions.hardSource)))
}

return plugins
}

extendConfig(config) {
if (typeof this.options.build.extend === 'function') {
const extendedConfig = this.options.build.extend.call(
const { extend } = this.buildContext.buildOptions
if (typeof extend === 'function') {
const extendedConfig = extend.call(
this.builder, config, { loaders: this.loaders, ...this.nuxtEnv }
)
// Only overwrite config when something is returned for backwards compatibility
Expand All @@ -405,17 +414,17 @@ export default class WebpackBaseConfig {

config() {
// Prioritize nested node_modules in webpack search path (#2558)
const webpackModulesDir = ['node_modules'].concat(this.options.modulesDir)
const webpackModulesDir = ['node_modules'].concat(this.buildContext.options.modulesDir)

const config = {
name: this.name,
mode: this.buildMode,
mode: this.mode,
devtool: this.devtool,
optimization: this.optimization(),
output: this.output(),
performance: {
maxEntrypointSize: 1000 * 1024,
hints: this.options.dev ? false : 'warning'
hints: this.dev ? false : 'warning'
},
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.json', '.vue', '.jsx', '.ts', '.tsx'],
Expand Down

0 comments on commit 9860eb6

Please sign in to comment.