Nuxt/packages/nuxt3/src/builder/webpack/presets/base.ts

234 lines
6.3 KiB
TypeScript
Raw Normal View History

2020-09-02 12:27:27 +00:00
import { resolve, normalize } from 'path'
import TimeFixPlugin from 'time-fix-plugin'
import WebpackBar from 'webpackbar'
import { DefinePlugin, Configuration } from 'webpack'
2021-01-20 14:43:43 +00:00
// import FriendlyErrorsWebpackPlugin from '@nuxt/friendly-errors-webpack-plugin'
2020-09-02 12:27:27 +00:00
import { isUrl, urlJoin, TARGETS } from 'src/utils'
import escapeRegExp from 'lodash/escapeRegExp'
import WarningIgnorePlugin from '../plugins/warning-ignore'
import { WebpackConfigContext, applyPresets, fileName } from '../utils/config'
export function base (ctx: WebpackConfigContext) {
applyPresets(ctx, [
baseAlias,
baseConfig,
basePlugins,
baseResolve
])
}
function baseConfig (ctx: WebpackConfigContext) {
const { options } = ctx
ctx.config = {
name: ctx.name,
2021-01-20 14:43:43 +00:00
entry: { app: [resolve(options.buildDir, `entry.${ctx.name}`)] },
2020-09-02 12:27:27 +00:00
module: { rules: [] },
plugins: [],
externals: [],
optimization: {
...options.build.optimization as any,
minimizer: []
},
mode: ctx.isDev ? 'development' : 'production',
cache: getCache(ctx),
output: getOutput(ctx),
2020-10-29 17:05:29 +00:00
stats: 'errors-warnings',
2020-09-02 12:27:27 +00:00
...ctx.config
}
}
function basePlugins (ctx: WebpackConfigContext) {
const { config, options, nuxt } = ctx
// Add timefix-plugin before others plugins
if (options.dev) {
config.plugins.push(new TimeFixPlugin())
}
// User plugins
config.plugins.push(...(options.build.plugins || []))
// Ignore empty warnings
config.plugins.push(new WarningIgnorePlugin(getWarningIgnoreFilter(ctx)))
// Provide env via DefinePlugin
config.plugins.push(new DefinePlugin(getEnv(ctx)))
// Friendly errors
2021-01-20 14:43:43 +00:00
// if (
// ctx.isServer ||
// (ctx.isDev && !options.build.quiet && options.build.friendlyErrors)
// ) {
// ctx.config.plugins.push(
// new FriendlyErrorsWebpackPlugin({
// clearConsole: false,
// reporter: 'consola',
// logLevel: 'WARNING'
// })
// )
// }
2020-09-02 12:27:27 +00:00
// Webpackbar
const colors = {
client: 'green',
server: 'orange',
modern: 'blue'
}
config.plugins.push(new WebpackBar({
name: ctx.name,
color: colors[ctx.name],
2021-01-20 15:44:52 +00:00
reporters: ['basic', 'stats'],
basic: true,
2021-01-20 15:44:52 +00:00
stats: !ctx.isDev,
2020-09-02 12:27:27 +00:00
reporter: {
change: (_, { shortPath }) => {
if (!ctx.isServer) {
nuxt.callHook('bundler:change', shortPath)
}
},
done: (stats) => {
if (stats.hasErrors) {
nuxt.callHook('bundler:error')
}
},
allDone: () => {
nuxt.callHook('bundler:done')
},
progress ({ statesArray }) {
nuxt.callHook('bundler:progress', statesArray)
}
}
}))
}
function baseAlias (ctx: WebpackConfigContext) {
2021-01-20 14:43:43 +00:00
const { options } = ctx
2020-09-02 12:27:27 +00:00
ctx.alias = {
'nuxt/app': options.appDir,
'~build': options.buildDir,
2020-09-02 12:27:27 +00:00
...options.alias,
...ctx.alias
}
}
function baseResolve (ctx: WebpackConfigContext) {
const { options, config } = ctx
// Prioritize nested node_modules in webpack search path (#2558)
// TODO: this might be refactored as default modulesDir?
const webpackModulesDir = ['node_modules'].concat(options.modulesDir)
config.resolve = {
extensions: ['.wasm', '.mjs', '.js', '.ts', '.json', '.vue', '.jsx', '.tsx'],
alias: ctx.alias,
modules: webpackModulesDir,
...config.resolve
}
config.resolveLoader = {
modules: webpackModulesDir,
...config.resolveLoader
}
}
export function baseTranspile (ctx: WebpackConfigContext) {
const { options } = ctx
const transpile = [
/\.vue\.js/i, // include SFCs in node_modules
/consola\/src/
]
for (let pattern of options.build.transpile) {
if (typeof pattern === 'function') {
pattern = pattern(ctx)
}
if (typeof pattern === 'string') {
const posixModule = pattern.replace(/\\/g, '/')
// TODO: should only do for clientside? (hint: pathNormalize)
transpile.push(new RegExp(escapeRegExp(normalize(posixModule))))
} else if (pattern instanceof RegExp) {
transpile.push(pattern)
}
}
// TODO: unique
ctx.transpile = [...transpile, ...ctx.transpile]
}
function getCache (ctx: WebpackConfigContext): Configuration['cache'] {
const { options } = ctx
if (!options.build.cache) {
return false
}
return {
type: 'filesystem',
cacheDirectory: resolve('node_modules/.cache/@nuxt/webpack/'),
buildDependencies: {
config: [...options._nuxtConfigFiles]
},
...(options.build.cache as any),
name
}
}
function getOutput (ctx: WebpackConfigContext): Configuration['output'] {
const { options } = ctx
return {
path: resolve(options.buildDir, 'dist', ctx.isServer ? 'server' : 'client'),
filename: fileName(ctx, 'app'),
chunkFilename: fileName(ctx, 'chunk'),
publicPath: isUrl(options.build.publicPath)
? options.build.publicPath
2020-09-02 12:27:27 +00:00
: urlJoin(options.router.base, options.build.publicPath)
}
}
function getWarningIgnoreFilter (ctx: WebpackConfigContext) {
const { options } = ctx
const filters = [
// Hide warnings about plugins without a default export (#1179)
warn => warn.name === 'ModuleDependencyWarning' &&
warn.message.includes('export \'default\'') &&
warn.message.includes('nuxt_plugin_'),
...(options.build.warningIgnoreFilters || [])
]
return warn => !filters.some(ignoreFilter => ignoreFilter(warn))
}
function getEnv (ctx: WebpackConfigContext) {
const { options } = ctx
const _env = {
'process.env.NODE_ENV': JSON.stringify(ctx.config.mode),
'process.mode': JSON.stringify(ctx.config.mode),
'process.dev': options.dev,
'process.static': options.target === TARGETS.static,
'process.target': JSON.stringify(options.target),
'process.env.VUE_ENV': JSON.stringify(ctx.name),
'process.browser': ctx.isClient,
'process.client': ctx.isClient,
'process.server': ctx.isServer,
'process.modern': ctx.isModern
}
if (options.build.aggressiveCodeRemoval) {
_env['typeof process'] = JSON.stringify(ctx.isServer ? 'object' : 'undefined')
_env['typeof window'] = _env['typeof document'] = JSON.stringify(!ctx.isServer ? 'object' : 'undefined')
}
Object.entries(options.env).forEach(([key, value]) => {
const isNative = ['boolean', 'number'].includes(typeof value)
_env['process.env.' + key] = isNative ? value : JSON.stringify(value)
})
return _env
}