mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-27 08:02:01 +00:00
refactor: unify context in webpack module (#5054)
This commit is contained in:
parent
3ed9f3e6a6
commit
9860eb6a7c
@ -6,6 +6,10 @@ export default class BuildContext {
|
|||||||
this.isStatic = false
|
this.isStatic = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get buildOptions() {
|
||||||
|
return this.options.build
|
||||||
|
}
|
||||||
|
|
||||||
get plugins() {
|
get plugins() {
|
||||||
return this._builder.plugins
|
return this._builder.plugins
|
||||||
}
|
}
|
||||||
|
@ -20,4 +20,14 @@ describe('builder: buildContext', () => {
|
|||||||
const context = new BuildContext(builder)
|
const context = new BuildContext(builder)
|
||||||
expect(context.plugins).toEqual(builder.plugins)
|
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)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -19,8 +19,8 @@ import PerfLoader from './utils/perf-loader'
|
|||||||
const glob = pify(Glob)
|
const glob = pify(Glob)
|
||||||
|
|
||||||
export class WebpackBundler {
|
export class WebpackBundler {
|
||||||
constructor(context) {
|
constructor(buildContext) {
|
||||||
this.context = context
|
this.buildContext = buildContext
|
||||||
// Fields that set on build
|
// Fields that set on build
|
||||||
this.compilers = []
|
this.compilers = []
|
||||||
this.compilersWatching = []
|
this.compilersWatching = []
|
||||||
@ -28,7 +28,7 @@ export class WebpackBundler {
|
|||||||
this.hotMiddleware = {}
|
this.hotMiddleware = {}
|
||||||
|
|
||||||
// Initialize shared MFS for dev
|
// Initialize shared MFS for dev
|
||||||
if (this.context.options.dev) {
|
if (this.buildContext.options.dev) {
|
||||||
this.mfs = new MFS()
|
this.mfs = new MFS()
|
||||||
|
|
||||||
// TODO: Enable when async FS required
|
// TODO: Enable when async FS required
|
||||||
@ -38,7 +38,7 @@ export class WebpackBundler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async build() {
|
async build() {
|
||||||
const { options } = this.context
|
const { options } = this.buildContext
|
||||||
|
|
||||||
const compilersOptions = []
|
const compilersOptions = []
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ export class WebpackBundler {
|
|||||||
compilersOptions.push(serverConfig)
|
compilersOptions.push(serverConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const p of this.context.plugins) {
|
for (const p of this.buildContext.plugins) {
|
||||||
// Client config
|
// Client config
|
||||||
if (!clientConfig.resolve.alias[p.name]) {
|
if (!clientConfig.resolve.alias[p.name]) {
|
||||||
clientConfig.resolve.alias[p.name] = p.mode === 'server' ? './empty.js' : p.src
|
clientConfig.resolve.alias[p.name] = p.mode === 'server' ? './empty.js' : p.src
|
||||||
@ -78,7 +78,7 @@ export class WebpackBundler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check styleResource existence
|
// Check styleResource existence
|
||||||
const { styleResources } = this.context.options.build
|
const { styleResources } = this.buildContext.options.build
|
||||||
if (styleResources && Object.keys(styleResources).length) {
|
if (styleResources && Object.keys(styleResources).length) {
|
||||||
consola.warn(
|
consola.warn(
|
||||||
'Using styleResources without the nuxt-style-resources-module is not suggested and can lead to severe performance issues.',
|
'Using styleResources without the nuxt-style-resources-module is not suggested and can lead to severe performance issues.',
|
||||||
@ -86,7 +86,7 @@ export class WebpackBundler {
|
|||||||
)
|
)
|
||||||
for (const ext of Object.keys(styleResources)) {
|
for (const ext of Object.keys(styleResources)) {
|
||||||
await Promise.all(wrapArray(styleResources[ext]).map(async (p) => {
|
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) {
|
if (!styleResourceFiles || styleResourceFiles.length === 0) {
|
||||||
throw new Error(`Style Resource not found: ${p}`)
|
throw new Error(`Style Resource not found: ${p}`)
|
||||||
@ -122,7 +122,7 @@ export class WebpackBundler {
|
|||||||
|
|
||||||
async webpackCompile(compiler) {
|
async webpackCompile(compiler) {
|
||||||
const { name } = compiler.options
|
const { name } = compiler.options
|
||||||
const { nuxt, options } = this.context
|
const { nuxt, options } = this.buildContext
|
||||||
|
|
||||||
await nuxt.callHook('build:compile', { name, compiler })
|
await nuxt.callHook('build:compile', { name, compiler })
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ export class WebpackBundler {
|
|||||||
consola.debug('Adding webpack middleware...')
|
consola.debug('Adding webpack middleware...')
|
||||||
|
|
||||||
const { name } = compiler.options
|
const { name } = compiler.options
|
||||||
const { nuxt: { server }, options } = this.context
|
const { nuxt: { server }, options } = this.buildContext
|
||||||
const { client, ...hotMiddlewareOptions } = options.build.hotMiddleware || {}
|
const { client, ...hotMiddlewareOptions } = options.build.hotMiddleware || {}
|
||||||
|
|
||||||
// Create webpack dev middleware
|
// Create webpack dev middleware
|
||||||
@ -255,6 +255,6 @@ export class WebpackBundler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
forGenerate() {
|
forGenerate() {
|
||||||
this.context.isStatic = true
|
this.buildContext.isStatic = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,16 +20,9 @@ import WarnFixPlugin from '../plugins/warnfix'
|
|||||||
import { reservedVueTags } from '../utils/reserved-tags'
|
import { reservedVueTags } from '../utils/reserved-tags'
|
||||||
|
|
||||||
export default class WebpackBaseConfig {
|
export default class WebpackBaseConfig {
|
||||||
constructor(builder, options) {
|
constructor(builder) {
|
||||||
this.name = options.name
|
|
||||||
this.isServer = options.isServer
|
|
||||||
this.isModern = options.isModern
|
|
||||||
this.builder = builder
|
this.builder = builder
|
||||||
this.nuxt = builder.context.nuxt
|
this.buildContext = builder.buildContext
|
||||||
this.isStatic = builder.context.isStatic
|
|
||||||
this.options = builder.context.options
|
|
||||||
this.loaders = this.options.build.loaders
|
|
||||||
this.buildMode = this.options.dev ? 'development' : 'production'
|
|
||||||
this.modulesToTranspile = this.normalizeTranspile()
|
this.modulesToTranspile = this.normalizeTranspile()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,17 +36,29 @@ export default class WebpackBaseConfig {
|
|||||||
|
|
||||||
get nuxtEnv() {
|
get nuxtEnv() {
|
||||||
return {
|
return {
|
||||||
isDev: this.options.dev,
|
isDev: this.dev,
|
||||||
isServer: this.isServer,
|
isServer: this.isServer,
|
||||||
isClient: !this.isServer,
|
isClient: !this.isServer,
|
||||||
isModern: !!this.isModern
|
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() {
|
normalizeTranspile() {
|
||||||
// include SFCs in node_modules
|
// include SFCs in node_modules
|
||||||
const items = [/\.vue\.js/i]
|
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) {
|
if (pattern instanceof RegExp) {
|
||||||
items.push(pattern)
|
items.push(pattern)
|
||||||
} else {
|
} else {
|
||||||
@ -65,7 +70,7 @@ export default class WebpackBaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBabelOptions() {
|
getBabelOptions() {
|
||||||
const options = clone(this.options.build.babel)
|
const options = clone(this.buildContext.buildOptions.babel)
|
||||||
|
|
||||||
if (typeof options.presets === 'function') {
|
if (typeof options.presets === 'function') {
|
||||||
options.presets = options.presets({ isServer: this.isServer })
|
options.presets = options.presets({ isServer: this.isServer })
|
||||||
@ -86,11 +91,11 @@ export default class WebpackBaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFileName(key) {
|
getFileName(key) {
|
||||||
let fileName = this.options.build.filenames[key]
|
let fileName = this.buildContext.buildOptions.filenames[key]
|
||||||
if (typeof fileName === 'function') {
|
if (typeof fileName === 'function') {
|
||||||
fileName = fileName(this.nuxtEnv)
|
fileName = fileName(this.nuxtEnv)
|
||||||
}
|
}
|
||||||
if (this.options.dev) {
|
if (this.dev) {
|
||||||
const hash = /\[(chunkhash|contenthash|hash)(?::(\d+))?]/.exec(fileName)
|
const hash = /\[(chunkhash|contenthash|hash)(?::(\d+))?]/.exec(fileName)
|
||||||
if (hash) {
|
if (hash) {
|
||||||
consola.warn(`Notice: Please do not use ${hash[1]} in dev mode to prevent memory leak`)
|
consola.warn(`Notice: Please do not use ${hash[1]} in dev mode to prevent memory leak`)
|
||||||
@ -105,11 +110,11 @@ export default class WebpackBaseConfig {
|
|||||||
|
|
||||||
env() {
|
env() {
|
||||||
const env = {
|
const env = {
|
||||||
'process.env.NODE_ENV': JSON.stringify(this.buildMode),
|
'process.env.NODE_ENV': JSON.stringify(this.mode),
|
||||||
'process.mode': JSON.stringify(this.options.mode),
|
'process.mode': JSON.stringify(this.mode),
|
||||||
'process.static': this.isStatic
|
'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] =
|
env['process.env.' + key] =
|
||||||
['boolean', 'number'].includes(typeof value)
|
['boolean', 'number'].includes(typeof value)
|
||||||
? value
|
? value
|
||||||
@ -119,19 +124,21 @@ export default class WebpackBaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
output() {
|
output() {
|
||||||
|
const {
|
||||||
|
options: { buildDir, router },
|
||||||
|
buildOptions: { publicPath }
|
||||||
|
} = this.buildContext
|
||||||
return {
|
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'),
|
filename: this.getFileName('app'),
|
||||||
futureEmitAssets: true, // TODO: Remove when using webpack 5
|
futureEmitAssets: true, // TODO: Remove when using webpack 5
|
||||||
chunkFilename: this.getFileName('chunk'),
|
chunkFilename: this.getFileName('chunk'),
|
||||||
publicPath: isUrl(this.options.build.publicPath)
|
publicPath: isUrl(publicPath) ? publicPath : urlJoin(router.base, publicPath)
|
||||||
? this.options.build.publicPath
|
|
||||||
: urlJoin(this.options.router.base, this.options.build.publicPath)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
optimization() {
|
optimization() {
|
||||||
const optimization = cloneDeep(this.options.build.optimization)
|
const optimization = cloneDeep(this.buildContext.buildOptions.optimization)
|
||||||
|
|
||||||
if (optimization.minimize && optimization.minimizer === undefined) {
|
if (optimization.minimize && optimization.minimizer === undefined) {
|
||||||
optimization.minimizer = this.minimizer()
|
optimization.minimizer = this.minimizer()
|
||||||
@ -142,13 +149,14 @@ export default class WebpackBaseConfig {
|
|||||||
|
|
||||||
minimizer() {
|
minimizer() {
|
||||||
const minimizer = []
|
const minimizer = []
|
||||||
|
const { terser, cache } = this.buildContext.buildOptions
|
||||||
|
|
||||||
// https://github.com/webpack-contrib/terser-webpack-plugin
|
// https://github.com/webpack-contrib/terser-webpack-plugin
|
||||||
if (this.options.build.terser) {
|
if (terser) {
|
||||||
minimizer.push(
|
minimizer.push(
|
||||||
new TerserWebpackPlugin(Object.assign({
|
new TerserWebpackPlugin(Object.assign({
|
||||||
parallel: true,
|
parallel: true,
|
||||||
cache: this.options.build.cache,
|
cache,
|
||||||
sourceMap: this.devtool && /source-?map/.test(this.devtool),
|
sourceMap: this.devtool && /source-?map/.test(this.devtool),
|
||||||
extractComments: {
|
extractComments: {
|
||||||
filename: 'LICENSES'
|
filename: 'LICENSES'
|
||||||
@ -164,7 +172,7 @@ export default class WebpackBaseConfig {
|
|||||||
reserved: reservedVueTags
|
reserved: reservedVueTags
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, this.options.build.terser))
|
}, terser))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +180,7 @@ export default class WebpackBaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
alias() {
|
alias() {
|
||||||
const { srcDir, rootDir, dir: { assets: assetsDir, static: staticDir } } = this.options
|
const { srcDir, rootDir, dir: { assets: assetsDir, static: staticDir } } = this.buildContext.options
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'~': path.join(srcDir),
|
'~': path.join(srcDir),
|
||||||
@ -185,10 +193,9 @@ export default class WebpackBaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rules() {
|
rules() {
|
||||||
const perfLoader = new PerfLoader(this)
|
const perfLoader = new PerfLoader(this.name, this.buildContext)
|
||||||
const styleLoader = new StyleLoader(
|
const styleLoader = new StyleLoader(
|
||||||
this.options,
|
this.buildContext,
|
||||||
this.nuxt,
|
|
||||||
{ isServer: this.isServer, perfLoader }
|
{ isServer: this.isServer, perfLoader }
|
||||||
)
|
)
|
||||||
const babelLoader = {
|
const babelLoader = {
|
||||||
@ -329,25 +336,26 @@ export default class WebpackBaseConfig {
|
|||||||
|
|
||||||
plugins() {
|
plugins() {
|
||||||
const plugins = []
|
const plugins = []
|
||||||
|
const { nuxt, buildOptions } = this.buildContext
|
||||||
|
|
||||||
// Add timefix-plugin before others plugins
|
// Add timefix-plugin before others plugins
|
||||||
if (this.options.dev) {
|
if (this.dev) {
|
||||||
plugins.push(new TimeFixPlugin())
|
plugins.push(new TimeFixPlugin())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSS extraction)
|
// CSS extraction)
|
||||||
if (this.options.build.extractCSS) {
|
if (buildOptions.extractCSS) {
|
||||||
plugins.push(new ExtractCssChunksPlugin(Object.assign({
|
plugins.push(new ExtractCssChunksPlugin(Object.assign({
|
||||||
filename: this.getFileName('css'),
|
filename: this.getFileName('css'),
|
||||||
chunkFilename: this.getFileName('css'),
|
chunkFilename: this.getFileName('css'),
|
||||||
// TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132
|
// TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132
|
||||||
reloadAll: true
|
reloadAll: true
|
||||||
}, this.options.build.extractCSS)))
|
}, buildOptions.extractCSS)))
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins.push(new VueLoader.VueLoaderPlugin())
|
plugins.push(new VueLoader.VueLoaderPlugin())
|
||||||
|
|
||||||
plugins.push(...(this.options.build.plugins || []))
|
plugins.push(...(buildOptions.plugins || []))
|
||||||
|
|
||||||
// Hide warnings about plugins without a default export (#1179)
|
// Hide warnings about plugins without a default export (#1179)
|
||||||
plugins.push(new WarnFixPlugin())
|
plugins.push(new WarnFixPlugin())
|
||||||
@ -362,37 +370,38 @@ export default class WebpackBaseConfig {
|
|||||||
'profile',
|
'profile',
|
||||||
'stats'
|
'stats'
|
||||||
],
|
],
|
||||||
basic: !this.options.build.quiet && env.minimalCLI,
|
basic: !buildOptions.quiet && env.minimalCLI,
|
||||||
fancy: !this.options.build.quiet && !env.minimalCLI,
|
fancy: !buildOptions.quiet && !env.minimalCLI,
|
||||||
profile: !this.options.build.quiet && this.options.build.profile,
|
profile: !buildOptions.quiet && buildOptions.profile,
|
||||||
stats: !this.options.build.quiet && !this.options.dev && this.options.build.stats,
|
stats: !buildOptions.quiet && !this.dev && buildOptions.stats,
|
||||||
reporter: {
|
reporter: {
|
||||||
change: (_, { shortPath }) => {
|
change: (_, { shortPath }) => {
|
||||||
if (!this.isServer) {
|
if (!this.isServer) {
|
||||||
this.nuxt.callHook('bundler:change', shortPath)
|
nuxt.callHook('bundler:change', shortPath)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
done: (context) => {
|
done: (buildContext) => {
|
||||||
if (context.hasErrors) {
|
if (buildContext.hasErrors) {
|
||||||
this.nuxt.callHook('bundler:error')
|
nuxt.callHook('bundler:error')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
allDone: () => {
|
allDone: () => {
|
||||||
this.nuxt.callHook('bundler:done')
|
nuxt.callHook('bundler:done')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if (this.options.build.hardSource) {
|
if (buildOptions.hardSource) {
|
||||||
plugins.push(new HardSourcePlugin(Object.assign({}, this.options.build.hardSource)))
|
plugins.push(new HardSourcePlugin(Object.assign({}, buildOptions.hardSource)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return plugins
|
return plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
extendConfig(config) {
|
extendConfig(config) {
|
||||||
if (typeof this.options.build.extend === 'function') {
|
const { extend } = this.buildContext.buildOptions
|
||||||
const extendedConfig = this.options.build.extend.call(
|
if (typeof extend === 'function') {
|
||||||
|
const extendedConfig = extend.call(
|
||||||
this.builder, config, { loaders: this.loaders, ...this.nuxtEnv }
|
this.builder, config, { loaders: this.loaders, ...this.nuxtEnv }
|
||||||
)
|
)
|
||||||
// Only overwrite config when something is returned for backwards compatibility
|
// Only overwrite config when something is returned for backwards compatibility
|
||||||
@ -405,17 +414,17 @@ export default class WebpackBaseConfig {
|
|||||||
|
|
||||||
config() {
|
config() {
|
||||||
// Prioritize nested node_modules in webpack search path (#2558)
|
// 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 = {
|
const config = {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
mode: this.buildMode,
|
mode: this.mode,
|
||||||
devtool: this.devtool,
|
devtool: this.devtool,
|
||||||
optimization: this.optimization(),
|
optimization: this.optimization(),
|
||||||
output: this.output(),
|
output: this.output(),
|
||||||
performance: {
|
performance: {
|
||||||
maxEntrypointSize: 1000 * 1024,
|
maxEntrypointSize: 1000 * 1024,
|
||||||
hints: this.options.dev ? false : 'warning'
|
hints: this.dev ? false : 'warning'
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.wasm', '.mjs', '.js', '.json', '.vue', '.jsx', '.ts', '.tsx'],
|
extensions: ['.wasm', '.mjs', '.js', '.json', '.vue', '.jsx', '.ts', '.tsx'],
|
||||||
|
@ -14,12 +14,15 @@ import VueSSRClientPlugin from '../plugins/vue/client'
|
|||||||
import WebpackBaseConfig from './base'
|
import WebpackBaseConfig from './base'
|
||||||
|
|
||||||
export default class WebpackClientConfig extends WebpackBaseConfig {
|
export default class WebpackClientConfig extends WebpackBaseConfig {
|
||||||
constructor(builder, options) {
|
constructor(builder) {
|
||||||
super(builder, options || { name: 'client', isServer: false })
|
super(builder)
|
||||||
|
this.name = 'client'
|
||||||
|
this.isServer = false
|
||||||
|
this.isModern = false
|
||||||
}
|
}
|
||||||
|
|
||||||
getFileName(...args) {
|
getFileName(...args) {
|
||||||
if (this.options.build.analyze) {
|
if (this.buildContext.buildOptions.analyze) {
|
||||||
const [key] = args
|
const [key] = args
|
||||||
if (['app', 'chunk'].includes(key)) {
|
if (['app', 'chunk'].includes(key)) {
|
||||||
return `${this.isModern ? 'modern-' : ''}[name].js`
|
return `${this.isModern ? 'modern-' : ''}[name].js`
|
||||||
@ -44,7 +47,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
// Small, known and common modules which are usually used project-wise
|
// Small, known and common modules which are usually used project-wise
|
||||||
// Sum of them may not be more than 244 KiB
|
// Sum of them may not be more than 244 KiB
|
||||||
if (
|
if (
|
||||||
this.options.build.splitChunks.commons === true &&
|
this.buildContext.buildOptions.splitChunks.commons === true &&
|
||||||
optimization.splitChunks.cacheGroups.commons === undefined
|
optimization.splitChunks.cacheGroups.commons === undefined
|
||||||
) {
|
) {
|
||||||
optimization.splitChunks.cacheGroups.commons = {
|
optimization.splitChunks.cacheGroups.commons = {
|
||||||
@ -60,14 +63,13 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
|
|
||||||
minimizer() {
|
minimizer() {
|
||||||
const minimizer = super.minimizer()
|
const minimizer = super.minimizer()
|
||||||
|
const { optimizeCSS } = this.buildContext.buildOptions
|
||||||
|
|
||||||
// https://github.com/NMFR/optimize-css-assets-webpack-plugin
|
// https://github.com/NMFR/optimize-css-assets-webpack-plugin
|
||||||
// https://github.com/webpack-contrib/mini-css-extract-plugin#minimizing-for-production
|
// https://github.com/webpack-contrib/mini-css-extract-plugin#minimizing-for-production
|
||||||
// TODO: Remove OptimizeCSSAssetsPlugin when upgrading to webpack 5
|
// TODO: Remove OptimizeCSSAssetsPlugin when upgrading to webpack 5
|
||||||
if (this.options.build.optimizeCSS) {
|
if (optimizeCSS) {
|
||||||
minimizer.push(
|
minimizer.push(new OptimizeCSSAssetsPlugin(Object.assign({}, optimizeCSS)))
|
||||||
new OptimizeCSSAssetsPlugin(Object.assign({}, this.options.build.optimizeCSS))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return minimizer
|
return minimizer
|
||||||
@ -75,14 +77,15 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
|
|
||||||
plugins() {
|
plugins() {
|
||||||
const plugins = super.plugins()
|
const plugins = super.plugins()
|
||||||
|
const { buildOptions, options: { appTemplatePath, buildDir, rootDir, modern } } = this.buildContext
|
||||||
|
|
||||||
// Generate output HTML for SSR
|
// Generate output HTML for SSR
|
||||||
if (this.options.build.ssr) {
|
if (buildOptions.ssr) {
|
||||||
plugins.push(
|
plugins.push(
|
||||||
new HTMLPlugin({
|
new HTMLPlugin({
|
||||||
filename: '../server/index.ssr.html',
|
filename: '../server/index.ssr.html',
|
||||||
template: this.options.appTemplatePath,
|
template: appTemplatePath,
|
||||||
minify: this.options.build.html.minify,
|
minify: buildOptions.html.minify,
|
||||||
inject: false // Resources will be injected using bundleRenderer
|
inject: false // Resources will be injected using bundleRenderer
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -91,8 +94,8 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
plugins.push(
|
plugins.push(
|
||||||
new HTMLPlugin({
|
new HTMLPlugin({
|
||||||
filename: '../server/index.spa.html',
|
filename: '../server/index.spa.html',
|
||||||
template: this.options.appTemplatePath,
|
template: appTemplatePath,
|
||||||
minify: this.options.build.html.minify,
|
minify: buildOptions.html.minify,
|
||||||
inject: true,
|
inject: true,
|
||||||
chunksSortMode: 'dependency'
|
chunksSortMode: 'dependency'
|
||||||
}),
|
}),
|
||||||
@ -102,53 +105,53 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
new webpack.DefinePlugin(this.env())
|
new webpack.DefinePlugin(this.env())
|
||||||
)
|
)
|
||||||
|
|
||||||
if (this.options.dev) {
|
if (this.dev) {
|
||||||
// TODO: webpackHotUpdate is not defined: https://github.com/webpack/webpack/issues/6693
|
// TODO: webpackHotUpdate is not defined: https://github.com/webpack/webpack/issues/6693
|
||||||
plugins.push(new webpack.HotModuleReplacementPlugin())
|
plugins.push(new webpack.HotModuleReplacementPlugin())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Webpack Bundle Analyzer
|
// Webpack Bundle Analyzer
|
||||||
// https://github.com/webpack-contrib/webpack-bundle-analyzer
|
// https://github.com/webpack-contrib/webpack-bundle-analyzer
|
||||||
if (!this.options.dev && this.options.build.analyze) {
|
if (!this.dev && buildOptions.analyze) {
|
||||||
const statsDir = path.resolve(this.options.buildDir, 'stats')
|
const statsDir = path.resolve(buildDir, 'stats')
|
||||||
|
|
||||||
plugins.push(new BundleAnalyzer.BundleAnalyzerPlugin(Object.assign({
|
plugins.push(new BundleAnalyzer.BundleAnalyzerPlugin(Object.assign({
|
||||||
analyzerMode: 'static',
|
analyzerMode: 'static',
|
||||||
defaultSizes: 'gzip',
|
defaultSizes: 'gzip',
|
||||||
generateStatsFile: true,
|
generateStatsFile: true,
|
||||||
openAnalyzer: !this.options.build.quiet,
|
openAnalyzer: !buildOptions.quiet,
|
||||||
reportFilename: path.resolve(statsDir, `${this.name}.html`),
|
reportFilename: path.resolve(statsDir, `${this.name}.html`),
|
||||||
statsFilename: path.resolve(statsDir, `${this.name}.json`)
|
statsFilename: path.resolve(statsDir, `${this.name}.json`)
|
||||||
}, this.options.build.analyze)))
|
}, buildOptions.analyze)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.modern) {
|
if (modern) {
|
||||||
plugins.push(new ModernModePlugin({
|
plugins.push(new ModernModePlugin({
|
||||||
targetDir: path.resolve(this.options.buildDir, 'dist', 'client'),
|
targetDir: path.resolve(buildDir, 'dist', 'client'),
|
||||||
isModernBuild: this.isModern
|
isModernBuild: this.isModern
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.build.crossorigin) {
|
if (buildOptions.crossorigin) {
|
||||||
plugins.push(new CorsPlugin({
|
plugins.push(new CorsPlugin({
|
||||||
crossorigin: this.options.build.crossorigin
|
crossorigin: buildOptions.crossorigin
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeScript type checker
|
// TypeScript type checker
|
||||||
// Only performs once per client compilation and only if `ts-loader` checker is not used (transpileOnly: true)
|
// Only performs once per client compilation and only if `ts-loader` checker is not used (transpileOnly: true)
|
||||||
if (!this.isModern && this.loaders.ts.transpileOnly && this.options.build.useForkTsChecker) {
|
if (!this.isModern && this.loaders.ts.transpileOnly && buildOptions.useForkTsChecker) {
|
||||||
const forkTsCheckerResolvedPath = this.nuxt.resolver.resolveModule('fork-ts-checker-webpack-plugin')
|
const forkTsCheckerResolvedPath = this.buildContext.nuxt.resolver.resolveModule('fork-ts-checker-webpack-plugin')
|
||||||
if (forkTsCheckerResolvedPath) {
|
if (forkTsCheckerResolvedPath) {
|
||||||
const ForkTsCheckerWebpackPlugin = require(forkTsCheckerResolvedPath)
|
const ForkTsCheckerWebpackPlugin = require(forkTsCheckerResolvedPath)
|
||||||
plugins.push(new ForkTsCheckerWebpackPlugin(Object.assign({
|
plugins.push(new ForkTsCheckerWebpackPlugin(Object.assign({
|
||||||
vue: true,
|
vue: true,
|
||||||
tsconfig: path.resolve(this.options.rootDir, 'tsconfig.json'),
|
tsconfig: path.resolve(rootDir, 'tsconfig.json'),
|
||||||
// https://github.com/Realytics/fork-ts-checker-webpack-plugin#options - tslint: boolean | string - So we set it false if file not found
|
// https://github.com/Realytics/fork-ts-checker-webpack-plugin#options - tslint: boolean | string - So we set it false if file not found
|
||||||
tslint: (tslintPath => fs.existsSync(tslintPath) && tslintPath)(path.resolve(this.options.rootDir, 'tslint.json')),
|
tslint: (tslintPath => fs.existsSync(tslintPath) && tslintPath)(path.resolve(rootDir, 'tslint.json')),
|
||||||
formatter: 'codeframe',
|
formatter: 'codeframe',
|
||||||
logger: consola
|
logger: consola
|
||||||
}, this.options.build.useForkTsChecker)))
|
}, buildOptions.useForkTsChecker)))
|
||||||
} else {
|
} else {
|
||||||
consola.warn('You need to install `fork-ts-checker-webpack-plugin` as devDependency to enable TypeScript type checking !')
|
consola.warn('You need to install `fork-ts-checker-webpack-plugin` as devDependency to enable TypeScript type checking !')
|
||||||
}
|
}
|
||||||
@ -159,8 +162,12 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
|
|
||||||
config() {
|
config() {
|
||||||
const config = super.config()
|
const config = super.config()
|
||||||
|
const {
|
||||||
|
options: { router, buildDir },
|
||||||
|
buildOptions: { hotMiddleware, quiet, friendlyErrors }
|
||||||
|
} = this.buildContext
|
||||||
|
|
||||||
const { client = {} } = this.options.build.hotMiddleware || {}
|
const { client = {} } = hotMiddleware || {}
|
||||||
const { ansiColors, overlayStyles, ...options } = client
|
const { ansiColors, overlayStyles, ...options } = client
|
||||||
const hotMiddlewareClientOptions = {
|
const hotMiddlewareClientOptions = {
|
||||||
reload: true,
|
reload: true,
|
||||||
@ -170,17 +177,17 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
...options,
|
...options,
|
||||||
name: this.name
|
name: this.name
|
||||||
}
|
}
|
||||||
const clientPath = `${this.options.router.base}/__webpack_hmr/${this.name}`
|
const clientPath = `${router.base}/__webpack_hmr/${this.name}`
|
||||||
const hotMiddlewareClientOptionsStr =
|
const hotMiddlewareClientOptionsStr =
|
||||||
`${querystring.stringify(hotMiddlewareClientOptions)}&path=${clientPath}`.replace(/\/\//g, '/')
|
`${querystring.stringify(hotMiddlewareClientOptions)}&path=${clientPath}`.replace(/\/\//g, '/')
|
||||||
|
|
||||||
// Entry points
|
// Entry points
|
||||||
config.entry = {
|
config.entry = {
|
||||||
app: [path.resolve(this.options.buildDir, 'client.js')]
|
app: [path.resolve(buildDir, 'client.js')]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add HMR support
|
// Add HMR support
|
||||||
if (this.options.dev) {
|
if (this.dev) {
|
||||||
config.entry.app.unshift(
|
config.entry.app.unshift(
|
||||||
// https://github.com/webpack-contrib/webpack-hot-middleware/issues/53#issuecomment-162823945
|
// https://github.com/webpack-contrib/webpack-hot-middleware/issues/53#issuecomment-162823945
|
||||||
'eventsource-polyfill',
|
'eventsource-polyfill',
|
||||||
@ -190,7 +197,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add friendly error plugin
|
// Add friendly error plugin
|
||||||
if (this.options.dev && !this.options.build.quiet && this.options.build.friendlyErrors) {
|
if (this.dev && !quiet && friendlyErrors) {
|
||||||
config.plugins.push(
|
config.plugins.push(
|
||||||
new FriendlyErrorsWebpackPlugin({
|
new FriendlyErrorsWebpackPlugin({
|
||||||
clearConsole: false,
|
clearConsole: false,
|
||||||
|
@ -2,8 +2,10 @@ import clone from 'lodash/clone'
|
|||||||
import WebpackClientConfig from './client'
|
import WebpackClientConfig from './client'
|
||||||
|
|
||||||
export default class WebpackModernConfig extends WebpackClientConfig {
|
export default class WebpackModernConfig extends WebpackClientConfig {
|
||||||
constructor(builder) {
|
constructor(...args) {
|
||||||
super(builder, { name: 'modern', isServer: false, isModern: true })
|
super(...args)
|
||||||
|
this.name = 'modern'
|
||||||
|
this.isModern = true
|
||||||
}
|
}
|
||||||
|
|
||||||
env() {
|
env() {
|
||||||
@ -13,7 +15,7 @@ export default class WebpackModernConfig extends WebpackClientConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBabelOptions() {
|
getBabelOptions() {
|
||||||
const options = clone(this.options.build.babel)
|
const options = clone(this.buildContext.buildOptions.babel)
|
||||||
|
|
||||||
options.presets = [
|
options.presets = [
|
||||||
[
|
[
|
||||||
|
@ -9,8 +9,10 @@ import VueSSRServerPlugin from '../plugins/vue/server'
|
|||||||
import WebpackBaseConfig from './base'
|
import WebpackBaseConfig from './base'
|
||||||
|
|
||||||
export default class WebpackServerConfig extends WebpackBaseConfig {
|
export default class WebpackServerConfig extends WebpackBaseConfig {
|
||||||
constructor(builder) {
|
constructor(...args) {
|
||||||
super(builder, { name: 'server', isServer: true })
|
super(...args)
|
||||||
|
this.name = 'server'
|
||||||
|
this.isServer = true
|
||||||
this.whitelist = this.normalizeWhitelist()
|
this.whitelist = this.normalizeWhitelist()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,7 +20,7 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
|
|||||||
const whitelist = [
|
const whitelist = [
|
||||||
/\.(?!js(x|on)?$)/i
|
/\.(?!js(x|on)?$)/i
|
||||||
]
|
]
|
||||||
for (const pattern of this.options.build.transpile) {
|
for (const pattern of this.buildContext.buildOptions.transpile) {
|
||||||
if (pattern instanceof RegExp) {
|
if (pattern instanceof RegExp) {
|
||||||
whitelist.push(pattern)
|
whitelist.push(pattern)
|
||||||
} else {
|
} else {
|
||||||
@ -68,7 +70,7 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
|
|||||||
target: 'node',
|
target: 'node',
|
||||||
node: false,
|
node: false,
|
||||||
entry: {
|
entry: {
|
||||||
app: [path.resolve(this.options.buildDir, 'server.js')]
|
app: [path.resolve(this.buildContext.options.buildDir, 'server.js')]
|
||||||
},
|
},
|
||||||
output: Object.assign({}, config.output, {
|
output: Object.assign({}, config.output, {
|
||||||
filename: 'server.js',
|
filename: 'server.js',
|
||||||
@ -85,8 +87,8 @@ export default class WebpackServerConfig extends WebpackBaseConfig {
|
|||||||
// https://webpack.js.org/configuration/externals/#externals
|
// https://webpack.js.org/configuration/externals/#externals
|
||||||
// https://github.com/liady/webpack-node-externals
|
// https://github.com/liady/webpack-node-externals
|
||||||
// https://vue-loader.vuejs.org/migrating.html#ssr-externals
|
// https://vue-loader.vuejs.org/migrating.html#ssr-externals
|
||||||
if (!this.options.build.standalone) {
|
if (!this.buildContext.buildOptions.standalone) {
|
||||||
this.options.modulesDir.forEach((dir) => {
|
this.buildContext.options.modulesDir.forEach((dir) => {
|
||||||
if (fs.existsSync(dir)) {
|
if (fs.existsSync(dir)) {
|
||||||
config.externals.push(
|
config.externals.push(
|
||||||
nodeExternals({
|
nodeExternals({
|
||||||
|
@ -6,10 +6,10 @@ 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(config) {
|
constructor(name, buildContext) {
|
||||||
this.name = config.name
|
this.name = name
|
||||||
this.options = config.options
|
this.buildContext = buildContext
|
||||||
this.workerPools = PerfLoader.defaultPools(this.options)
|
this.workerPools = PerfLoader.defaultPools({ dev: buildContext.options.dev })
|
||||||
return new Proxy(this, {
|
return new Proxy(this, {
|
||||||
get(target, name) {
|
get(target, name) {
|
||||||
return target[name] ? target[name] : target.use.bind(target, name)
|
return target[name] ? target[name] : target.use.bind(target, name)
|
||||||
@ -25,13 +25,13 @@ export default class PerfLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static warmupAll(options) {
|
static warmupAll({ dev }) {
|
||||||
options = PerfLoader.defaultPools(options)
|
const pools = PerfLoader.defaultPools({ dev })
|
||||||
PerfLoader.warmup(options.js, [
|
PerfLoader.warmup(pools.js, [
|
||||||
require.resolve('babel-loader'),
|
require.resolve('babel-loader'),
|
||||||
require.resolve('@babel/preset-env')
|
require.resolve('@babel/preset-env')
|
||||||
])
|
])
|
||||||
PerfLoader.warmup(options.css, ['css-loader'])
|
PerfLoader.warmup(pools.css, ['css-loader'])
|
||||||
}
|
}
|
||||||
|
|
||||||
static warmup(...args) {
|
static warmup(...args) {
|
||||||
@ -41,7 +41,7 @@ export default class PerfLoader {
|
|||||||
use(poolName) {
|
use(poolName) {
|
||||||
const loaders = []
|
const loaders = []
|
||||||
|
|
||||||
if (this.options.build.cache) {
|
if (this.buildContext.buildOptions.cache) {
|
||||||
loaders.push({
|
loaders.push({
|
||||||
loader: 'cache-loader',
|
loader: 'cache-loader',
|
||||||
options: {
|
options: {
|
||||||
@ -50,7 +50,7 @@ export default class PerfLoader {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.build.parallel) {
|
if (this.buildContext.buildOptions.parallel) {
|
||||||
const pool = this.workerPools[poolName]
|
const pool = this.workerPools[poolName]
|
||||||
if (pool) {
|
if (pool) {
|
||||||
loaders.push({
|
loaders.push({
|
||||||
|
@ -19,34 +19,29 @@ export const orderPresets = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class PostcssConfig {
|
export default class PostcssConfig {
|
||||||
constructor(options, nuxt) {
|
constructor(buildContext) {
|
||||||
this.nuxt = nuxt
|
this.buildContext = buildContext
|
||||||
this.dev = options.dev
|
}
|
||||||
this.postcss = options.build.postcss
|
|
||||||
this.srcDir = options.srcDir
|
get postcssOptions() {
|
||||||
this.rootDir = options.rootDir
|
return this.buildContext.buildOptions.postcss
|
||||||
this.cssSourceMap = options.build.cssSourceMap
|
|
||||||
this.modulesDir = options.modulesDir
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get defaultConfig() {
|
get defaultConfig() {
|
||||||
|
const { dev, srcDir, rootDir, modulesDir } = this.buildContext.options
|
||||||
return {
|
return {
|
||||||
sourceMap: this.cssSourceMap,
|
sourceMap: this.buildContext.buildOptions.cssSourceMap,
|
||||||
plugins: {
|
plugins: {
|
||||||
// https://github.com/postcss/postcss-import
|
// https://github.com/postcss/postcss-import
|
||||||
'postcss-import': {
|
'postcss-import': {
|
||||||
resolve: createResolver({
|
resolve: createResolver({
|
||||||
alias: {
|
alias: {
|
||||||
'~': path.join(this.srcDir),
|
'~': path.join(srcDir),
|
||||||
'~~': path.join(this.rootDir),
|
'~~': path.join(rootDir),
|
||||||
'@': path.join(this.srcDir),
|
'@': path.join(srcDir),
|
||||||
'@@': path.join(this.rootDir)
|
'@@': path.join(rootDir)
|
||||||
},
|
},
|
||||||
modules: [
|
modules: [ srcDir, rootDir, ...modulesDir ]
|
||||||
this.srcDir,
|
|
||||||
this.rootDir,
|
|
||||||
...this.modulesDir
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -55,7 +50,7 @@ export default class PostcssConfig {
|
|||||||
|
|
||||||
// https://github.com/csstools/postcss-preset-env
|
// https://github.com/csstools/postcss-preset-env
|
||||||
'postcss-preset-env': this.preset || {},
|
'postcss-preset-env': this.preset || {},
|
||||||
'cssnano': this.dev ? false : { preset: 'default' }
|
'cssnano': dev ? false : { preset: 'default' }
|
||||||
},
|
},
|
||||||
// Array, String or Function
|
// Array, String or Function
|
||||||
order: 'cssnanoLast'
|
order: 'cssnanoLast'
|
||||||
@ -65,7 +60,8 @@ export default class PostcssConfig {
|
|||||||
searchConfigFile() {
|
searchConfigFile() {
|
||||||
// Search for postCSS config file and use it if exists
|
// Search for postCSS config file and use it if exists
|
||||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||||
for (const dir of [this.srcDir, this.rootDir]) {
|
const { srcDir, rootDir } = this.buildContext.options
|
||||||
|
for (const dir of [ srcDir, rootDir ]) {
|
||||||
for (const file of [
|
for (const file of [
|
||||||
'postcss.config.js',
|
'postcss.config.js',
|
||||||
'.postcssrc.js',
|
'.postcssrc.js',
|
||||||
@ -82,12 +78,12 @@ export default class PostcssConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configFromFile() {
|
configFromFile() {
|
||||||
const loaderConfig = (this.postcss && this.postcss.config) || {}
|
const loaderConfig = (this.postcssOptions && this.postcssOptions.config) || {}
|
||||||
loaderConfig.path = loaderConfig.path || this.searchConfigFile()
|
loaderConfig.path = loaderConfig.path || this.searchConfigFile()
|
||||||
|
|
||||||
if (loaderConfig.path) {
|
if (loaderConfig.path) {
|
||||||
return {
|
return {
|
||||||
sourceMap: this.cssSourceMap,
|
sourceMap: this.buildContext.buildOptions.cssSourceMap,
|
||||||
config: loaderConfig
|
config: loaderConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +113,7 @@ export default class PostcssConfig {
|
|||||||
// Map postcss plugins into instances on object mode once
|
// Map postcss plugins into instances on object mode once
|
||||||
config.plugins = this.sortPlugins(config)
|
config.plugins = this.sortPlugins(config)
|
||||||
.map((p) => {
|
.map((p) => {
|
||||||
const plugin = this.nuxt.resolver.requireModule(p)
|
const plugin = this.buildContext.nuxt.resolver.requireModule(p)
|
||||||
const opts = plugins[p]
|
const opts = plugins[p]
|
||||||
if (opts === false) {
|
if (opts === false) {
|
||||||
return // Disabled
|
return // Disabled
|
||||||
@ -130,7 +126,7 @@ export default class PostcssConfig {
|
|||||||
|
|
||||||
config() {
|
config() {
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (!this.postcss) {
|
if (!this.postcssOptions) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +135,7 @@ export default class PostcssConfig {
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
config = this.normalize(cloneDeep(this.postcss))
|
config = this.normalize(cloneDeep(this.postcssOptions))
|
||||||
|
|
||||||
// Apply default plugins
|
// Apply default plugins
|
||||||
if (isPureObject(config)) {
|
if (isPureObject(config)) {
|
||||||
|
@ -6,24 +6,20 @@ import { wrapArray } from '@nuxt/utils'
|
|||||||
import PostcssConfig from './postcss'
|
import PostcssConfig from './postcss'
|
||||||
|
|
||||||
export default class StyleLoader {
|
export default class StyleLoader {
|
||||||
constructor(options, nuxt, { isServer, perfLoader }) {
|
constructor(buildContext, { isServer, perfLoader }) {
|
||||||
|
this.buildContext = buildContext
|
||||||
this.isServer = isServer
|
this.isServer = isServer
|
||||||
this.perfLoader = perfLoader
|
this.perfLoader = perfLoader
|
||||||
this.rootDir = options.rootDir
|
|
||||||
this.loaders = {
|
|
||||||
vueStyle: options.build.loaders.vueStyle,
|
|
||||||
css: options.build.loaders.css,
|
|
||||||
cssModules: options.build.loaders.cssModules
|
|
||||||
}
|
|
||||||
this.extractCSS = options.build.extractCSS
|
|
||||||
this.resources = options.build.styleResources
|
|
||||||
this.sourceMap = Boolean(options.build.cssSourceMap)
|
|
||||||
|
|
||||||
if (options.build.postcss) {
|
if (buildContext.options.build.postcss) {
|
||||||
this.postcssConfig = new PostcssConfig(options, nuxt)
|
this.postcssConfig = new PostcssConfig(buildContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get extractCSS() {
|
||||||
|
return this.buildContext.buildOptions.extractCSS
|
||||||
|
}
|
||||||
|
|
||||||
get exportOnlyLocals() {
|
get exportOnlyLocals() {
|
||||||
return Boolean(this.isServer && this.extractCSS)
|
return Boolean(this.isServer && this.extractCSS)
|
||||||
}
|
}
|
||||||
@ -34,19 +30,20 @@ export default class StyleLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
styleResource(ext) {
|
styleResource(ext) {
|
||||||
const extResource = this.resources[ext]
|
const { buildOptions: { styleResources }, options: { rootDir } } = this.buildContext
|
||||||
|
const extResource = styleResources[ext]
|
||||||
// style-resources-loader
|
// style-resources-loader
|
||||||
// https://github.com/yenshih/style-resources-loader
|
// https://github.com/yenshih/style-resources-loader
|
||||||
if (!extResource) {
|
if (!extResource) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const patterns = wrapArray(extResource).map(p => path.resolve(this.rootDir, p))
|
const patterns = wrapArray(extResource).map(p => path.resolve(rootDir, p))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loader: 'style-resources-loader',
|
loader: 'style-resources-loader',
|
||||||
options: Object.assign(
|
options: Object.assign(
|
||||||
{ patterns },
|
{ patterns },
|
||||||
this.resources.options || {}
|
styleResources.options || {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +63,7 @@ export default class StyleLoader {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
loader: 'postcss-loader',
|
loader: 'postcss-loader',
|
||||||
options: Object.assign({ sourceMap: this.sourceMap }, config)
|
options: Object.assign({ sourceMap: this.buildContext.buildOptions.cssSourceMap }, config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,32 +91,34 @@ export default class StyleLoader {
|
|||||||
styleLoader() {
|
styleLoader() {
|
||||||
return this.extract() || {
|
return this.extract() || {
|
||||||
loader: 'vue-style-loader',
|
loader: 'vue-style-loader',
|
||||||
options: this.loaders.vueStyle
|
options: this.buildContext.buildOptions.loaders.vueStyle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(ext, loaders = []) {
|
apply(ext, loaders = []) {
|
||||||
|
const { css, cssModules } = this.buildContext.buildOptions.loaders
|
||||||
|
|
||||||
const customLoaders = [].concat(
|
const customLoaders = [].concat(
|
||||||
this.postcss(),
|
this.postcss(),
|
||||||
this.normalize(loaders),
|
this.normalize(loaders),
|
||||||
this.styleResource(ext)
|
this.styleResource(ext)
|
||||||
).filter(Boolean)
|
).filter(Boolean)
|
||||||
|
|
||||||
this.loaders.css.importLoaders = this.loaders.cssModules.importLoaders = customLoaders.length
|
css.importLoaders = cssModules.importLoaders = customLoaders.length
|
||||||
|
|
||||||
return [
|
return [
|
||||||
// This matches <style module>
|
// This matches <style module>
|
||||||
{
|
{
|
||||||
resourceQuery: /module/,
|
resourceQuery: /module/,
|
||||||
use: this.perfLoader.css().concat(
|
use: this.perfLoader.css().concat(
|
||||||
this.cssModules(this.loaders.cssModules),
|
this.cssModules(cssModules),
|
||||||
customLoaders
|
customLoaders
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
// This matches plain <style> or <style scoped>
|
// This matches plain <style> or <style scoped>
|
||||||
{
|
{
|
||||||
use: this.perfLoader.css().concat(
|
use: this.perfLoader.css().concat(
|
||||||
this.css(this.loaders.css),
|
this.css(css),
|
||||||
customLoaders
|
customLoaders
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ describe('basic generate', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('Check builder', () => {
|
test('Check builder', () => {
|
||||||
expect(builder.bundleBuilder.context.isStatic).toBe(true)
|
expect(builder.bundleBuilder.buildContext.isStatic).toBe(true)
|
||||||
expect(builder.build).toHaveBeenCalledTimes(1)
|
expect(builder.build).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -15,16 +15,18 @@ describe('webpack configuration', () => {
|
|||||||
])
|
])
|
||||||
expect(PerfLoader.warmup).toHaveBeenCalledWith(css, ['css-loader'])
|
expect(PerfLoader.warmup).toHaveBeenCalledWith(css, ['css-loader'])
|
||||||
|
|
||||||
const perfLoader = new PerfLoader({
|
const perfLoader = new PerfLoader(
|
||||||
name: 'test-perf',
|
'test-perf',
|
||||||
|
{
|
||||||
options: {
|
options: {
|
||||||
dev: true,
|
dev: true
|
||||||
build: {
|
},
|
||||||
|
buildOptions: {
|
||||||
parallel: true,
|
parallel: true,
|
||||||
cache: true
|
cache: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
expect(perfLoader.workerPools).toMatchObject({ js, css })
|
expect(perfLoader.workerPools).toMatchObject({ js, css })
|
||||||
const loaders = perfLoader.use('js')
|
const loaders = perfLoader.use('js')
|
||||||
const cacheDirectory = path.resolve('node_modules/.cache/cache-loader/test-perf')
|
const cacheDirectory = path.resolve('node_modules/.cache/cache-loader/test-perf')
|
||||||
|
Loading…
Reference in New Issue
Block a user