2020-09-02 12:27:27 +00:00
|
|
|
import { resolve, normalize } from 'path'
|
|
|
|
import TimeFixPlugin from 'time-fix-plugin'
|
|
|
|
import WebpackBar from 'webpackbar'
|
2021-02-17 20:15:47 +00:00
|
|
|
import consola from 'consola'
|
2020-09-02 12:27:27 +00:00
|
|
|
import { DefinePlugin, Configuration } from 'webpack'
|
2021-02-17 20:15:47 +00:00
|
|
|
import FriendlyErrorsWebpackPlugin from '@nuxt/friendly-errors-webpack-plugin'
|
2021-04-03 13:38:07 +00:00
|
|
|
import { escapeRegExp } from 'lodash'
|
2021-04-02 19:38:11 +00:00
|
|
|
import { hasProtocol, joinURL } from 'ufo'
|
2020-09-02 12:27:27 +00:00
|
|
|
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-05-20 11:42:41 +00:00
|
|
|
entry: { app: [resolve(options.buildDir, 'entry')] },
|
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),
|
2021-02-17 20:15:47 +00:00
|
|
|
stats: 'none',
|
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-02-17 20:15:47 +00:00
|
|
|
if (
|
|
|
|
ctx.isServer ||
|
|
|
|
(ctx.isDev && !options.build.quiet && options.build.friendlyErrors)
|
|
|
|
) {
|
|
|
|
ctx.config.plugins.push(
|
|
|
|
new FriendlyErrorsWebpackPlugin({
|
|
|
|
clearConsole: false,
|
|
|
|
reporter: 'consola',
|
|
|
|
logLevel: 'ERROR' // TODO
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
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-02-17 20:15:47 +00:00
|
|
|
reporters: ['stats'],
|
2021-01-20 15:44:52 +00:00
|
|
|
stats: !ctx.isDev,
|
2020-09-02 12:27:27 +00:00
|
|
|
reporter: {
|
2021-04-02 19:38:11 +00:00
|
|
|
// @ts-ignore
|
2020-09-02 12:27:27 +00:00
|
|
|
change: (_, { shortPath }) => {
|
|
|
|
if (!ctx.isServer) {
|
|
|
|
nuxt.callHook('bundler:change', shortPath)
|
|
|
|
}
|
|
|
|
},
|
2021-02-17 20:15:47 +00:00
|
|
|
done: ({ state }) => {
|
|
|
|
if (state.hasErrors) {
|
2020-09-02 12:27:27 +00:00
|
|
|
nuxt.callHook('bundler:error')
|
2021-02-17 20:15:47 +00:00
|
|
|
} else {
|
|
|
|
consola.success(`${state.name} ${state.message}`)
|
2020-09-02 12:27:27 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
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 = {
|
2021-04-29 11:51:54 +00:00
|
|
|
'#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,
|
2021-04-21 15:10:53 +00:00
|
|
|
fullySpecified: false,
|
2020-09-02 12:27:27 +00:00
|
|
|
...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
|
|
|
|
|
2021-04-04 12:28:55 +00:00
|
|
|
if (!options.dev) {
|
2020-09-02 12:27:27 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-04-28 14:50:41 +00:00
|
|
|
// TODO: Disable for nuxt internal dev due to inconsistencies
|
|
|
|
// return {
|
|
|
|
// name: ctx.name,
|
|
|
|
// type: 'filesystem',
|
|
|
|
// cacheDirectory: resolve(ctx.options.rootDir, 'node_modules/.cache/webpack'),
|
|
|
|
// managedPaths: [
|
|
|
|
// ...ctx.options.modulesDir
|
|
|
|
// ],
|
|
|
|
// buildDependencies: {
|
|
|
|
// config: [
|
|
|
|
// ...ctx.options._nuxtConfigFiles
|
|
|
|
// ]
|
|
|
|
// }
|
|
|
|
// }
|
2020-09-02 12:27:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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'),
|
2021-04-02 19:38:11 +00:00
|
|
|
publicPath: hasProtocol(options.build.publicPath, true)
|
2020-11-16 08:33:33 +00:00
|
|
|
? options.build.publicPath
|
2021-04-02 19:38:11 +00:00
|
|
|
: joinURL(options.router.base, options.build.publicPath)
|
2020-09-02 12:27:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2021-04-02 19:38:11 +00:00
|
|
|
'process.static': options.target === 'static',
|
2020-09-02 12:27:27 +00:00
|
|
|
'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
|
|
|
|
}
|