%PDF- %PDF-
Direktori : /home/forge/takeaseat.eco-n-tech.co.uk/node_modules/@nuxt/webpack/dist/ |
Current File : //home/forge/takeaseat.eco-n-tech.co.uk/node_modules/@nuxt/webpack/dist/webpack.js |
/*! * @nuxt/webpack v2.15.4 (c) 2016-2021 * Released under the MIT License * Repository: https://github.com/nuxt/nuxt.js * Website: https://nuxtjs.org */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const path = require('path'); const pify = require('pify'); const webpack = require('webpack'); const Glob = require('glob'); const webpackDevMiddleware = require('webpack-dev-middleware'); const webpackHotMiddleware = require('webpack-hot-middleware'); const consola = require('consola'); const utils = require('@nuxt/utils'); const MFS = require('memory-fs'); const querystring = require('querystring'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const BundleAnalyzer = require('webpack-bundle-analyzer'); const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const FriendlyErrorsWebpackPlugin = require('@nuxt/friendly-errors-webpack-plugin'); const EventEmitter = require('events'); const hash = require('hash-sum'); const lodash = require('lodash'); const TimeFixPlugin = require('time-fix-plugin'); const VueLoader = require('vue-loader'); const ExtractCssChunksPlugin = require('extract-css-chunks-webpack-plugin'); const PnpWebpackPlugin = require('pnp-webpack-plugin'); const HardSourcePlugin = require('hard-source-webpack-plugin'); const TerserWebpackPlugin = require('terser-webpack-plugin'); const WebpackBar = require('webpackbar'); const env = require('std-env'); const semver = require('semver'); const ufo = require('ufo'); const threadLoader = require('thread-loader'); const fs = require('fs'); const createResolver = require('postcss-import-resolver'); const nodeExternals = require('webpack-node-externals'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n['default'] = e; return Object.freeze(n); } const path__default = /*#__PURE__*/_interopDefaultLegacy(path); const pify__default = /*#__PURE__*/_interopDefaultLegacy(pify); const webpack__default = /*#__PURE__*/_interopDefaultLegacy(webpack); const Glob__default = /*#__PURE__*/_interopDefaultLegacy(Glob); const webpackDevMiddleware__default = /*#__PURE__*/_interopDefaultLegacy(webpackDevMiddleware); const webpackHotMiddleware__default = /*#__PURE__*/_interopDefaultLegacy(webpackHotMiddleware); const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola); const MFS__default = /*#__PURE__*/_interopDefaultLegacy(MFS); const querystring__default = /*#__PURE__*/_interopDefaultLegacy(querystring); const HtmlWebpackPlugin__default = /*#__PURE__*/_interopDefaultLegacy(HtmlWebpackPlugin); const BundleAnalyzer__default = /*#__PURE__*/_interopDefaultLegacy(BundleAnalyzer); const OptimizeCSSAssetsPlugin__default = /*#__PURE__*/_interopDefaultLegacy(OptimizeCSSAssetsPlugin); const FriendlyErrorsWebpackPlugin__default = /*#__PURE__*/_interopDefaultLegacy(FriendlyErrorsWebpackPlugin); const EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter); const hash__default = /*#__PURE__*/_interopDefaultLegacy(hash); const TimeFixPlugin__default = /*#__PURE__*/_interopDefaultLegacy(TimeFixPlugin); const VueLoader__default = /*#__PURE__*/_interopDefaultLegacy(VueLoader); const ExtractCssChunksPlugin__default = /*#__PURE__*/_interopDefaultLegacy(ExtractCssChunksPlugin); const PnpWebpackPlugin__namespace = /*#__PURE__*/_interopNamespace(PnpWebpackPlugin); const HardSourcePlugin__default = /*#__PURE__*/_interopDefaultLegacy(HardSourcePlugin); const TerserWebpackPlugin__default = /*#__PURE__*/_interopDefaultLegacy(TerserWebpackPlugin); const WebpackBar__default = /*#__PURE__*/_interopDefaultLegacy(WebpackBar); const env__default = /*#__PURE__*/_interopDefaultLegacy(env); const semver__default = /*#__PURE__*/_interopDefaultLegacy(semver); const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); const createResolver__default = /*#__PURE__*/_interopDefaultLegacy(createResolver); const nodeExternals__default = /*#__PURE__*/_interopDefaultLegacy(nodeExternals); class AsyncMFS extends MFS__default['default'] {} const syncRegex = /Sync$/; const propsToPromisify = Object.getOwnPropertyNames(MFS__default['default'].prototype).filter(n => syncRegex.test(n)); for (const prop of propsToPromisify) { const asyncProp = prop.replace(syncRegex, ''); const origAsync = AsyncMFS.prototype[asyncProp]; AsyncMFS.prototype[asyncProp] = function (...args) { // Callback support for webpack if (origAsync && args.length && typeof args[args.length - 1] === 'function') { return origAsync.call(this, ...args) } try { return Promise.resolve(MFS__default['default'].prototype[prop].call(this, ...args)) } catch (error) { return Promise.reject(error) } }; } class CorsPlugin { constructor ({ crossorigin }) { this.crossorigin = crossorigin; } apply (compiler) { const ID = 'vue-cors-plugin'; compiler.hooks.compilation.tap(ID, (compilation) => { HtmlWebpackPlugin__default['default'].getHooks(compilation).alterAssetTagGroups.tap(ID, (data) => { if (!this.crossorigin) { return } [...data.headTags, ...data.bodyTags].forEach((tag) => { if (['script', 'link'].includes(tag.tagName)) { if (tag.attributes) { tag.attributes.crossorigin = this.crossorigin; } } }); }); }); } } /* * This file is based on @vue/cli-service (MIT) ModernModePlugin * https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/webpack/ModernModePlugin.js */ const legacyTemplateTags = {}; const legacyTemplateWatcher = new EventEmitter__default['default'](); class ModernModePlugin { constructor ({ targetDir, isModernBuild, noUnsafeInline }) { this.targetDir = targetDir; this.isModernBuild = isModernBuild; this.noUnsafeInline = noUnsafeInline; } apply (compiler) { if (!this.isModernBuild) { this.applyLegacy(compiler); } else { this.applyModern(compiler); } } getLegacyTemplateTags (name) { return new Promise((resolve) => { const tags = legacyTemplateTags[name]; if (tags) { return resolve(tags) } return legacyTemplateWatcher.once(name, () => { const tags = legacyTemplateTags[name]; return tags && resolve(tags) }) }) } applyLegacy (compiler) { const ID = 'nuxt-legacy-bundle'; compiler.hooks.compilation.tap(ID, (compilation) => { HtmlWebpackPlugin__default['default'].getHooks(compilation).alterAssetTagGroups.tap(ID, (data) => { HtmlWebpackPlugin__default['default'].getHooks(compilation).afterEmit.tap(ID, ({ outputName }) => { // get stats, write to disk legacyTemplateTags[data.plugin.options.filename] = data.bodyTags; legacyTemplateWatcher.emit(outputName); }); return data }); }); } applyModern (compiler) { const ID = 'nuxt-modern-bundle'; compiler.hooks.compilation.tap(ID, (compilation) => { HtmlWebpackPlugin__default['default'].getHooks(compilation).alterAssetTagGroups.tapPromise(ID, async (data) => { // use <script type="module"> for modern assets data.bodyTags.forEach((tag) => { if (tag.tagName === 'script' && tag.attributes) { tag.attributes.type = 'module'; } }); // use <link rel="modulepreload"> instead of <link rel="preload"> // for modern assets data.headTags.forEach((tag) => { if (tag.tagName === 'link' && tag.attributes.rel === 'preload' && tag.attributes.as === 'script') { tag.attributes.rel = 'modulepreload'; } }); // inject links for legacy assets as <script nomodule> const fileName = data.plugin.options.filename; const legacyScriptTags = (await this.getLegacyTemplateTags(fileName)) .filter(a => a.tagName === 'script' && a.attributes); for (const a of legacyScriptTags) { a.attributes.nomodule = true; data.bodyTags.push(a); } if (this.noUnsafeInline) { // inject the fix as an external script const safariFixFilename = 'safari-nomodule-fix.js'; const safariFixPath = legacyScriptTags[0].attributes.src .split('/') .slice(0, -1) .concat([safariFixFilename]) .join('/'); compilation.assets[safariFixFilename] = { source: () => Buffer.from(utils.safariNoModuleFix), size: () => Buffer.byteLength(utils.safariNoModuleFix) }; data.bodyTags.push({ tagName: 'script', closeTag: true, attributes: { src: safariFixPath } }); } else { // inject Safari 10 nomodule fix data.bodyTags.push({ tagName: 'script', closeTag: true, innerHTML: utils.safariNoModuleFix }); } delete legacyTemplateTags[fileName]; return data }); }); } } /** * This file is based on Vue.js (MIT) webpack plugins * https://github.com/vuejs/vue/blob/dev/src/server/webpack-plugin/util.js */ const validate = (compiler) => { if (compiler.options.target !== 'node') { consola__default['default'].warn('webpack config `target` should be "node".'); } if (compiler.options.output && compiler.options.output.libraryTarget !== 'commonjs2') { consola__default['default'].warn('webpack config `output.libraryTarget` should be "commonjs2".'); } if (!compiler.options.externals) { consola__default['default'].info( 'It is recommended to externalize dependencies in the server build for ' + 'better build performance.' ); } }; const isJSRegExp = /\.js(\?[^.]+)?$/; const isJS = file => isJSRegExp.test(file); const extractQueryPartJS = file => isJSRegExp.exec(file)[1]; const isCSS = file => /\.css(\?[^.]+)?$/.test(file); /** * This file is based on Vue.js (MIT) webpack plugins * https://github.com/vuejs/vue/blob/dev/src/server/webpack-plugin/client.js */ class VueSSRClientPlugin { constructor (options = {}) { this.options = Object.assign({ filename: null }, options); } apply (compiler) { compiler.hooks.emit.tapAsync('vue-client-plugin', (compilation, cb) => { const stats = compilation.getStats().toJson(); const allFiles = lodash.uniq(stats.assets .map(a => a.name)); const initialFiles = lodash.uniq(Object.keys(stats.entrypoints) .map(name => stats.entrypoints[name].assets) .reduce((assets, all) => all.concat(assets), []) .filter(file => isJS(file) || isCSS(file))); const asyncFiles = allFiles .filter(file => isJS(file) || isCSS(file)) .filter(file => !initialFiles.includes(file)); const assetsMapping = {}; stats.assets .filter(({ name }) => isJS(name)) .forEach(({ name, chunkNames }) => { const componentHash = hash__default['default'](chunkNames.join('|')); if (!assetsMapping[componentHash]) { assetsMapping[componentHash] = []; } assetsMapping[componentHash].push(name); }); const manifest = { publicPath: stats.publicPath, all: allFiles, initial: initialFiles, async: asyncFiles, modules: { /* [identifier: string]: Array<index: number> */ }, assetsMapping }; const { entrypoints, namedChunkGroups } = stats; const assetModules = stats.modules.filter(m => m.assets.length); const fileToIndex = file => manifest.all.indexOf(file); stats.modules.forEach((m) => { // Ignore modules duplicated in multiple chunks if (m.chunks.length === 1) { const [cid] = m.chunks; const chunk = stats.chunks.find(c => c.id === cid); if (!chunk || !chunk.files) { return } const id = m.identifier.replace(/\s\w+$/, ''); // remove appended hash const filesSet = new Set(chunk.files.map(fileToIndex)); for (const chunkName of chunk.names) { if (!entrypoints[chunkName]) { const chunkGroup = namedChunkGroups[chunkName]; if (chunkGroup) { for (const asset of chunkGroup.assets) { filesSet.add(fileToIndex(asset)); } } } } const files = Array.from(filesSet); manifest.modules[hash__default['default'](id)] = files; // In production mode, modules may be concatenated by scope hoisting // Include ConcatenatedModule for not losing module-component mapping if (Array.isArray(m.modules)) { for (const concatenatedModule of m.modules) { const id = hash__default['default'](concatenatedModule.identifier.replace(/\s\w+$/, '')); if (!manifest.modules[id]) { manifest.modules[id] = files; } } } // Find all asset modules associated with the same chunk assetModules.forEach((m) => { if (m.chunks.includes(cid)) { files.push.apply(files, m.assets.map(fileToIndex)); } }); } }); const src = JSON.stringify(manifest, null, 2); compilation.assets[this.options.filename] = { source: () => src, size: () => src.length }; cb(); }); } } // https://github.com/webpack-contrib/thread-loader // https://github.com/webpack-contrib/cache-loader class PerfLoader { constructor (name, buildContext, { resolveModule }) { this.name = name; this.buildContext = buildContext; this.workerPools = PerfLoader.defaultPools({ dev: buildContext.options.dev }); this.resolveModule = resolveModule; return new Proxy(this, { get (target, name) { return target[name] ? target[name] : target.use.bind(target, name) } }) } static defaultPools ({ dev }) { const poolTimeout = dev ? Infinity : 2000; return { js: { name: 'js', poolTimeout }, css: { name: 'css', poolTimeout } } } static warmupAll ({ dev, resolveModule }) { const pools = PerfLoader.defaultPools({ dev }); PerfLoader.warmup(pools.js, [ resolveModule('babel-loader'), resolveModule('@babel/preset-env') ]); PerfLoader.warmup(pools.css, [resolveModule('css-loader')]); } static warmup (...args) { threadLoader.warmup(...args); } use (poolName) { const loaders = []; if (this.buildContext.buildOptions.cache) { loaders.push({ loader: this.resolveModule('cache-loader'), options: { cacheDirectory: path__default['default'].resolve(`node_modules/.cache/cache-loader/${this.name}`) } }); } if (this.buildContext.buildOptions.parallel) { const pool = this.workerPools[poolName]; if (pool) { loaders.push({ loader: this.resolveModule('thread-loader'), options: pool }); } } return loaders } } const orderPresets$1 = { cssnanoLast (names) { const nanoIndex = names.indexOf('cssnano'); if (nanoIndex !== names.length - 1) { names.push(names.splice(nanoIndex, 1)[0]); } return names }, presetEnvLast (names) { const nanoIndex = names.indexOf('postcss-preset-env'); if (nanoIndex !== names.length - 1) { names.push(names.splice(nanoIndex, 1)[0]); } return names }, presetEnvAndCssnanoLast (names) { return orderPresets$1.cssnanoLast(orderPresets$1.presetEnvLast(names)) } }; function postcssConfigFileWarning$1 () { if (postcssConfigFileWarning$1.executed) { return } consola__default['default'].warn('Please use `build.postcss` in your nuxt.config.js instead of an external config file. Support for such files will be removed in Nuxt 3 as they remove all defaults set by Nuxt and can cause severe problems with features like alias resolving inside your CSS.'); postcssConfigFileWarning$1.executed = true; } class PostcssConfig$1 { constructor (buildContext) { this.buildContext = buildContext; } get postcssOptions () { return this.buildContext.buildOptions.postcss } get postcssImportAlias () { const alias = { ...this.buildContext.options.alias }; for (const key in alias) { if (key.startsWith('~')) { continue } const newKey = '~' + key; if (!alias[newKey]) { alias[newKey] = alias[key]; } } return alias } get defaultConfig () { const { dev, srcDir, rootDir, modulesDir } = this.buildContext.options; return { sourceMap: this.buildContext.buildOptions.cssSourceMap, plugins: { // https://github.com/postcss/postcss-import 'postcss-import': { resolve: createResolver__default['default']({ alias: this.postcssImportAlias, modules: [srcDir, rootDir, ...modulesDir] }) }, // https://github.com/postcss/postcss-url 'postcss-url': {}, // https://github.com/csstools/postcss-preset-env 'postcss-preset-env': this.preset || {}, cssnano: dev ? false : { preset: ['default', { // Keep quotes in font values to prevent from HEX conversion // https://github.com/nuxt/nuxt.js/issues/6306 minifyFontValues: { removeQuotes: false } }] } }, // Array, String or Function order: 'presetEnvAndCssnanoLast' } } searchConfigFile () { // 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; for (const dir of [srcDir, rootDir]) { for (const file of [ 'postcss.config.js', '.postcssrc.js', '.postcssrc', '.postcssrc.json', '.postcssrc.yaml' ]) { const configFile = path__default['default'].resolve(dir, file); if (fs__default['default'].existsSync(configFile)) { postcssConfigFileWarning$1(); return configFile } } } } configFromFile () { const loaderConfig = (this.postcssOptions && this.postcssOptions.config) || {}; loaderConfig.path = loaderConfig.path || this.searchConfigFile(); if (loaderConfig.path) { return { sourceMap: this.buildContext.buildOptions.cssSourceMap, config: loaderConfig } } } normalize (config) { // TODO: Remove in Nuxt 3 if (Array.isArray(config)) { consola__default['default'].warn('Using an Array as `build.postcss` will be deprecated in Nuxt 3. Please switch to the object' + ' declaration'); config = { plugins: config }; } return config } sortPlugins ({ plugins, order }) { const names = Object.keys(plugins); if (typeof order === 'string') { order = orderPresets$1[order]; } return typeof order === 'function' ? order(names, orderPresets$1) : (order || names) } loadPlugins (config) { const { plugins } = config; if (utils.isPureObject(plugins)) { // Map postcss plugins into instances on object mode once config.plugins = this.sortPlugins(config) .map((p) => { const plugin = this.buildContext.nuxt.resolver.requireModule(p, { paths: [__dirname] }); const opts = plugins[p]; if (opts === false) { return false // Disabled } return plugin(opts) }) .filter(Boolean); } } config () { /* istanbul ignore if */ if (!this.postcssOptions) { return false } let config = this.configFromFile(); if (config) { return config } config = this.normalize(lodash.cloneDeep(this.postcssOptions)); // Apply default plugins if (utils.isPureObject(config)) { if (config.preset) { this.preset = config.preset; delete config.preset; } if (Array.isArray(config.plugins)) { lodash.defaults(config, this.defaultConfig); } else { // Keep the order of default plugins config = lodash.merge({}, this.defaultConfig, config); this.loadPlugins(config); } return config } } } const orderPresets = { cssnanoLast (names) { const nanoIndex = names.indexOf('cssnano'); if (nanoIndex !== names.length - 1) { names.push(names.splice(nanoIndex, 1)[0]); } return names }, presetEnvLast (names) { const nanoIndex = names.indexOf('postcss-preset-env'); if (nanoIndex !== names.length - 1) { names.push(names.splice(nanoIndex, 1)[0]); } return names }, presetEnvAndCssnanoLast (names) { return orderPresets.cssnanoLast(orderPresets.presetEnvLast(names)) } }; function postcssConfigFileWarning () { if (postcssConfigFileWarning.executed) { return } consola__default['default'].warn('Please use `build.postcss` in your nuxt.config.js instead of an external config file. Support for such files will be removed in Nuxt 3 as they remove all defaults set by Nuxt and can cause severe problems with features like alias resolving inside your CSS.'); postcssConfigFileWarning.executed = true; } class PostcssConfig { constructor (buildContext) { this.buildContext = buildContext; } get cssSourceMap () { return this.buildContext.buildOptions.cssSourceMap } get postcssOptions () { return this.buildContext.buildOptions.postcss } get postcssImportAlias () { const alias = { ...this.buildContext.options.alias }; for (const key in alias) { if (key.startsWith('~')) { continue } const newKey = '~' + key; if (!alias[newKey]) { alias[newKey] = alias[key]; } } return alias } get defaultPostcssOptions () { const { dev, srcDir, rootDir, modulesDir } = this.buildContext.options; return { plugins: { // https://github.com/postcss/postcss-import 'postcss-import': { resolve: createResolver__default['default']({ alias: this.postcssImportAlias, modules: [srcDir, rootDir, ...modulesDir] }) }, // https://github.com/postcss/postcss-url 'postcss-url': {}, // https://github.com/csstools/postcss-preset-env // TODO: enable when https://github.com/csstools/postcss-preset-env/issues/191 gets closed // 'postcss-preset-env': this.preset || {}, cssnano: dev ? false : { preset: ['default', { // Keep quotes in font values to prevent from HEX conversion // https://github.com/nuxt/nuxt.js/issues/6306 minifyFontValues: { removeQuotes: false } }] } }, // Array, String or Function order: 'presetEnvAndCssnanoLast' } } searchConfigFile () { // 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; for (const dir of [srcDir, rootDir]) { for (const file of [ 'postcss.config.js', '.postcssrc.js', '.postcssrc', '.postcssrc.json', '.postcssrc.yaml' ]) { const configFile = path__default['default'].resolve(dir, file); if (fs__default['default'].existsSync(configFile)) { postcssConfigFileWarning(); return configFile } } } } configFromFile () { const loaderConfig = (this.postcssOptions && this.postcssOptions.config) || {}; loaderConfig.path = loaderConfig.path || this.searchConfigFile(); if (loaderConfig.path) { return { config: loaderConfig } } } normalize (postcssOptions) { // TODO: Remove in Nuxt 3 if (Array.isArray(postcssOptions)) { consola__default['default'].warn('Using an Array as `build.postcss` will be deprecated in Nuxt 3. Please switch to the object' + ' declaration'); postcssOptions = { plugins: postcssOptions }; } return postcssOptions } sortPlugins ({ plugins, order }) { const names = Object.keys(plugins); if (typeof order === 'string') { order = orderPresets[order]; } return typeof order === 'function' ? order(names, orderPresets) : (order || names) } loadPlugins (postcssOptions) { const { plugins } = postcssOptions; if (utils.isPureObject(plugins)) { // Map postcss plugins into instances on object mode once postcssOptions.plugins = this.sortPlugins(postcssOptions) .map((p) => { const plugin = this.buildContext.nuxt.resolver.requireModule(p, { paths: [__dirname] }); const opts = plugins[p]; if (opts === false) { return false // Disabled } return plugin(opts) }) .filter(Boolean); } } config () { /* istanbul ignore if */ if (!this.postcssOptions) { return false } let postcssOptions = this.configFromFile(); if (postcssOptions) { return { postcssOptions, sourceMap: this.cssSourceMap } } postcssOptions = this.normalize(lodash.cloneDeep(this.postcssOptions)); // Apply default plugins if (utils.isPureObject(postcssOptions)) { if (postcssOptions.preset) { this.preset = postcssOptions.preset; delete postcssOptions.preset; } if (Array.isArray(postcssOptions.plugins)) { lodash.defaults(postcssOptions, this.defaultPostcssOptions); } else { // Keep the order of default plugins postcssOptions = lodash.merge({}, this.defaultPostcssOptions, postcssOptions); this.loadPlugins(postcssOptions); } const { execute } = postcssOptions; delete postcssOptions.execute; delete postcssOptions.order; return { execute, postcssOptions, sourceMap: this.cssSourceMap } } } } class StyleLoader { constructor (buildContext, { isServer, perfLoader, resolveModule }) { this.buildContext = buildContext; this.isServer = isServer; this.perfLoader = perfLoader; this.resolveModule = resolveModule; const { postcss: postcssOptions } = buildContext.options.build; if (postcssOptions) { const postcss = require(resolveModule('postcss')); // postcss >= v8 if (!postcss.vendor) { this.postcssConfig = new PostcssConfig(buildContext); } else { this.postcssConfig = new PostcssConfig$1(buildContext); } } } get extractCSS () { return this.buildContext.buildOptions.extractCSS } get exportOnlyLocals () { return Boolean(this.isServer && this.extractCSS) } isUrlResolvingEnabled (url, resourcePath) { // Ignore absolute URLs, it will be handled by serve-static. return !url.startsWith('/') } normalize (loaders) { loaders = utils.wrapArray(loaders); return loaders.map(loader => (typeof loader === 'string' ? { loader } : loader)) } styleResource (ext) { const { buildOptions: { styleResources }, options: { rootDir } } = this.buildContext; const extResource = styleResources[ext]; // style-resources-loader // https://github.com/yenshih/style-resources-loader if (!extResource) { return } const patterns = utils.wrapArray(extResource).map(p => path__default['default'].resolve(rootDir, p)); return { loader: this.resolveModule('style-resources-loader'), options: Object.assign( { patterns }, styleResources.options || {} ) } } postcss () { // postcss-loader // https://github.com/postcss/postcss-loader if (!this.postcssConfig) { return } const config = this.postcssConfig.config(); if (!config) { return } return { loader: this.resolveModule('postcss-loader'), options: Object.assign({ sourceMap: this.buildContext.buildOptions.cssSourceMap }, config) } } css (options) { const cssLoader = { loader: this.resolveModule('css-loader'), options }; if (!options.url) { options.url = this.isUrlResolvingEnabled; } if (this.exportOnlyLocals) { options.modules = { ...options.modules, exportOnlyLocals: true }; return [cssLoader] } return [this.styleLoader(), cssLoader] } cssModules (options) { return this.css(options) } extract () { if (this.extractCSS) { const isDev = this.buildContext.options.dev; return { loader: ExtractCssChunksPlugin__default['default'].loader, options: { // TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132 // https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/161#issuecomment-500162574 reloadAll: isDev, hmr: isDev } } } } styleLoader () { return this.extract() || { loader: this.resolveModule('vue-style-loader'), options: this.buildContext.buildOptions.loaders.vueStyle } } apply (ext, loaders = []) { const { css, cssModules } = this.buildContext.buildOptions.loaders; const customLoaders = [].concat( this.postcss(), this.normalize(loaders), this.styleResource(ext) ).filter(Boolean); css.importLoaders = cssModules.importLoaders = customLoaders.length; return [ // This matches <style module> { resourceQuery: /module/, use: this.perfLoader.css().concat( this.cssModules(cssModules), customLoaders ) }, // This matches plain <style> or <style scoped> { use: this.perfLoader.css().concat( this.css(css), customLoaders ) } ] } } class WarningIgnorePlugin { constructor (filter) { this.filter = filter; } apply (compiler) /* istanbul ignore next */ { compiler.hooks.done.tap('warnfix-plugin', (stats) => { stats.compilation.warnings = stats.compilation.warnings.filter(this.filter); }); } } const reservedVueTags = [ // HTML tags 'html', 'body', 'base', 'head', 'link', 'meta', 'style', 'title', 'address', 'article', 'aside', 'footer', 'header', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hgroup', 'nav', 'section', 'div', 'dd', 'dl', 'dt', 'figcaption', 'figure', 'picture', 'hr', 'img', 'li', 'main', 'ol', 'p', 'pre', 'ul', 'a', 'b', 'abbr', 'bdi', 'bdo', 'br', 'cite', 'code', 'data', 'dfn', 'em', 'i', 'kbd', 'mark', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr', 'area', 'audio', 'map', 'track', 'video', 'embed', 'object', 'param', 'source', 'canvas', 'script', 'noscript', 'del', 'ins', 'caption', 'col', 'colgroup', 'table', 'thead', 'tbody', 'td', 'th', 'tr', 'button', 'datalist', 'fieldset', 'form', 'input', 'label', 'legend', 'meter', 'optgroup', 'option', 'output', 'progress', 'select', 'textarea', 'details', 'dialog', 'menu', 'menuitem', 'summary', 'content', 'element', 'shadow', 'template', 'blockquote', 'iframe', 'tfoot', // SVG tags 'svg', 'animate', 'circle', 'clippath', 'cursor', 'defs', 'desc', 'ellipse', 'filter', 'font-face', 'foreignObject', 'g', 'glyph', 'image', 'line', 'marker', 'mask', 'missing-glyph', 'path', 'pattern', 'polygon', 'polyline', 'rect', 'switch', 'symbol', 'text', 'textpath', 'tspan', 'use', 'view', // Vue built-in tags 'slot', 'component' ]; class WebpackBaseConfig { constructor (builder) { this.builder = builder; this.buildContext = builder.buildContext; this.resolveModule = id => utils.tryResolve(id, [this.buildContext.options.rootDir, __dirname]) || id; } get colors () { return { client: 'green', server: 'orange', modern: 'blue' } } get nuxtEnv () { return { isDev: this.dev, isServer: this.isServer, isClient: !this.isServer, isModern: Boolean(this.isModern), isLegacy: Boolean(!this.isModern) } } get mode () { return this.dev ? 'development' : 'production' } get target () { return this.buildContext.target } get dev () { return this.buildContext.options.dev } get loaders () { if (!this._loaders) { this._loaders = lodash.cloneDeep(this.buildContext.buildOptions.loaders); // sass-loader<8 support (#6460) const sassLoaderPKG = utils.getPKG('sass-loader'); if (sassLoaderPKG && semver__default['default'].lt(sassLoaderPKG.version, '8.0.0')) { const { sass } = this._loaders; sass.indentedSyntax = sass.sassOptions.indentedSyntax; delete sass.sassOptions.indentedSyntax; } } return this._loaders } get modulesToTranspile () { return [ /\.vue\.js/i, // include SFCs in node_modules /consola\/src/, /ufo/, // exports modern syntax for browser field ...this.normalizeTranspile({ pathNormalize: true }) ] } normalizeTranspile ({ pathNormalize = false } = {}) { const transpile = []; for (let pattern of this.buildContext.buildOptions.transpile) { if (typeof pattern === 'function') { pattern = pattern(this.nuxtEnv); } if (pattern instanceof RegExp) { transpile.push(pattern); } else if (typeof pattern === 'string') { const posixModule = pattern.replace(/\\/g, '/'); transpile.push(new RegExp(lodash.escapeRegExp( pathNormalize ? path__default['default'].normalize(posixModule) : posixModule ))); } } return transpile } getBabelOptions () { const envName = this.name; const { buildOptions: { corejs }, options: { rootDir } } = this.buildContext; const options = { ...this.buildContext.buildOptions.babel, envName }; if (options.configFile || options.babelrc) { return options } if (typeof options.plugins === 'function') { options.plugins = options.plugins( { envName, ...this.nuxtEnv } ); } // Auto detect corejs version let corejsVersion = corejs; if (corejsVersion === 'auto') { try { corejsVersion = Number.parseInt(utils.requireModule('core-js/package.json', rootDir).version.split('.')[0]); } catch (_err) { corejsVersion = 2; } } else { corejsVersion = Number.parseInt(corejsVersion); } if (![2, 3].includes(corejsVersion)) { consola__default['default'].warn(`Invalid corejs version ${corejsVersion}! Please set "build.corejs" to either "auto", 2 or 3.`); corejsVersion = 2; } const defaultPreset = [this.resolveModule('@nuxt/babel-preset-app'), { corejs: { version: corejsVersion } }]; if (typeof options.presets === 'function') { options.presets = options.presets( { envName, ...this.nuxtEnv }, defaultPreset ); } if (!options.presets) { options.presets = [defaultPreset]; } return options } getFileName (key) { let fileName = this.buildContext.buildOptions.filenames[key]; if (typeof fileName === 'function') { fileName = fileName(this.nuxtEnv); } if (this.dev) { const hash = /\[(chunkhash|contenthash|hash)(?::(\d+))?]/.exec(fileName); if (hash) { consola__default['default'].warn(`Notice: Please do not use ${hash[1]} in dev mode to prevent memory leak`); } } if (this.buildContext.buildOptions.analyze && !fileName.includes('[name]')) { fileName = '[name].' + fileName; } return fileName } env () { const env = { 'process.env.NODE_ENV': JSON.stringify(this.mode), 'process.mode': JSON.stringify(this.mode), 'process.dev': this.dev, 'process.static': this.target === utils.TARGETS.static, 'process.target': JSON.stringify(this.target) }; if (this.buildContext.buildOptions.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]) => { env['process.env.' + key] = ['boolean', 'number'].includes(typeof value) ? value : JSON.stringify(value); }); return env } output () { const { options: { buildDir, router }, buildOptions: { publicPath } } = this.buildContext; return { path: path__default['default'].resolve(buildDir, 'dist', this.isServer ? 'server' : 'client'), filename: this.getFileName('app'), futureEmitAssets: true, // TODO: Remove when using webpack 5 chunkFilename: this.getFileName('chunk'), publicPath: utils.isUrl(publicPath) ? publicPath : ufo.isRelative(publicPath) ? publicPath.replace(/^\.+\//, '/') : utils.urlJoin(router.base, publicPath) } } optimization () { const optimization = lodash.cloneDeep(this.buildContext.buildOptions.optimization); if (optimization.minimize && optimization.minimizer === undefined) { optimization.minimizer = this.minimizer(); } return optimization } resolve () { // Prioritize nested node_modules in webpack search path (#2558) const webpackModulesDir = ['node_modules'].concat(this.buildContext.options.modulesDir); const resolvePath = [ ...(global.__NUXT_PREPATHS__ || []), this.buildContext.options.rootDir, __dirname, ...(global.__NUXT_PATHS__ || []), utils.resolveModule('@nuxt/vue-app'), utils.resolveModule('@nuxt/babel-preset-app') ]; const resolvePlugins = [PnpWebpackPlugin__namespace].concat(resolvePath.map(p => PnpWebpackPlugin__namespace.moduleLoader(p))); return { resolve: { extensions: ['.wasm', '.mjs', '.js', '.json', '.vue', '.jsx'], alias: this.alias(), modules: webpackModulesDir, plugins: resolvePlugins }, resolveLoader: { modules: [ path__default['default'].resolve(__dirname, '../node_modules'), ...webpackModulesDir ], plugins: resolvePlugins } } } minimizer () { const minimizer = []; const { terser, cache } = this.buildContext.buildOptions; // https://github.com/webpack-contrib/terser-webpack-plugin if (terser) { minimizer.push( new TerserWebpackPlugin__default['default'](Object.assign({ cache, extractComments: { condition: 'some', filename: 'LICENSES' }, terserOptions: { compress: { ecma: this.isModern ? 2015 : undefined }, mangle: { reserved: reservedVueTags } } }, terser)) ); } return minimizer } alias () { return { ...this.buildContext.options.alias, 'vue-meta': this.resolveModule(`vue-meta${this.isServer ? '' : '/dist/vue-meta.esm.browser.js'}`) } } rules () { const perfLoader = new PerfLoader(this.name, this.buildContext, { resolveModule: this.resolveModule }); const styleLoader = new StyleLoader( this.buildContext, { isServer: this.isServer, perfLoader, resolveModule: this.resolveModule } ); const babelLoader = { loader: this.resolveModule('babel-loader'), options: this.getBabelOptions() }; return [ { test: /\.vue$/i, loader: this.resolveModule('vue-loader'), options: this.loaders.vue }, { test: /\.pug$/i, oneOf: [ { resourceQuery: /^\?vue/i, use: [{ loader: this.resolveModule('pug-plain-loader'), options: this.loaders.pugPlain }] }, { use: [ this.resolveModule('raw-loader'), { loader: this.resolveModule('pug-plain-loader'), options: this.loaders.pugPlain } ] } ] }, { test: /\.m?jsx?$/i, exclude: (file) => { file = file.split(/node_modules(.*)/)[1]; // not exclude files outside node_modules if (!file) { return false } // item in transpile can be string or regex object return !this.modulesToTranspile.some(module => module.test(file)) }, use: perfLoader.js().concat(babelLoader) }, { test: /\.css$/i, oneOf: styleLoader.apply('css') }, { test: /\.p(ost)?css$/i, oneOf: styleLoader.apply('postcss') }, { test: /\.less$/i, oneOf: styleLoader.apply('less', { loader: this.resolveModule('less-loader'), options: this.loaders.less }) }, { test: /\.sass$/i, oneOf: styleLoader.apply('sass', { loader: this.resolveModule('sass-loader'), options: this.loaders.sass }) }, { test: /\.scss$/i, oneOf: styleLoader.apply('scss', { loader: this.resolveModule('sass-loader'), options: this.loaders.scss }) }, { test: /\.styl(us)?$/i, oneOf: styleLoader.apply('stylus', { loader: this.resolveModule('stylus-loader'), options: this.loaders.stylus }) }, { test: /\.(png|jpe?g|gif|svg|webp|avif)$/i, use: [{ loader: this.resolveModule('url-loader'), options: Object.assign( this.loaders.imgUrl, { name: this.getFileName('img') } ) }] }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i, use: [{ loader: this.resolveModule('url-loader'), options: Object.assign( this.loaders.fontUrl, { name: this.getFileName('font') } ) }] }, { test: /\.(webm|mp4|ogv)$/i, use: [{ loader: this.resolveModule('file-loader'), options: Object.assign( this.loaders.file, { name: this.getFileName('video') } ) }] } ] } plugins () { const plugins = []; const { nuxt, buildOptions } = this.buildContext; // Add timefix-plugin before others plugins if (this.dev) { plugins.push(new TimeFixPlugin__default['default']()); } // CSS extraction) if (buildOptions.extractCSS) { plugins.push(new ExtractCssChunksPlugin__default['default'](Object.assign({ filename: this.getFileName('css'), chunkFilename: this.getFileName('css') }, buildOptions.extractCSS))); } plugins.push(new VueLoader__default['default'].VueLoaderPlugin()); plugins.push(...(buildOptions.plugins || [])); plugins.push(new WarningIgnorePlugin(this.warningIgnoreFilter())); // Build progress indicator plugins.push(new WebpackBar__default['default']({ name: this.name, color: this.colors[this.name], reporters: [ 'basic', 'fancy', 'profile', 'stats' ], basic: !buildOptions.quiet && env__default['default'].minimalCLI, fancy: !buildOptions.quiet && !env__default['default'].minimalCLI, profile: !buildOptions.quiet && buildOptions.profile, stats: !buildOptions.quiet && !this.dev && buildOptions.stats, reporter: { change: (_, { shortPath }) => { if (!this.isServer) { nuxt.callHook('bundler:change', shortPath); } }, done: (buildContext) => { if (buildContext.hasErrors) { nuxt.callHook('bundler:error'); } }, allDone: () => { nuxt.callHook('bundler:done'); }, progress ({ statesArray }) { nuxt.callHook('bundler:progress', statesArray); } } })); if (buildOptions.hardSource) { // https://github.com/mzgoddard/hard-source-webpack-plugin plugins.push(new HardSourcePlugin__default['default']({ info: { level: 'warn' }, ...buildOptions.hardSource })); } return plugins } warningIgnoreFilter () { 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_'), ...(this.buildContext.buildOptions.warningIgnoreFilters || []) ]; return warn => !filters.some(ignoreFilter => ignoreFilter(warn)) } extendConfig (config) { const { extend } = this.buildContext.buildOptions; if (typeof extend === 'function') { const extendedConfig = extend.call( this.builder, config, { loaders: this.loaders, ...this.nuxtEnv } ) || config; const pragma = /@|#/; const { devtool } = extendedConfig; if (typeof devtool === 'string' && pragma.test(devtool)) { extendedConfig.devtool = devtool.replace(pragma, ''); consola__default['default'].warn(`devtool has been normalized to ${extendedConfig.devtool} as webpack documented value`); } return extendedConfig } return config } config () { const config = { name: this.name, mode: this.mode, devtool: this.devtool, optimization: this.optimization(), output: this.output(), performance: { maxEntrypointSize: 1000 * 1024, hints: this.dev ? false : 'warning' }, module: { rules: this.rules() }, plugins: this.plugins(), ...this.resolve() }; // Clone deep avoid leaking config between Client and Server const extendedConfig = lodash.cloneDeep(this.extendConfig(config)); return extendedConfig } } class WebpackClientConfig extends WebpackBaseConfig { constructor (builder) { super(builder); this.name = 'client'; this.isServer = false; this.isModern = false; } get devtool () { if (!this.dev) { return false } const scriptPolicy = this.getCspScriptPolicy(); const noUnsafeEval = scriptPolicy && !scriptPolicy.includes('\'unsafe-eval\''); return noUnsafeEval ? 'cheap-module-source-map' : 'cheap-module-eval-source-map' } getCspScriptPolicy () { const { csp } = this.buildContext.options.render; if (csp) { const { policies = {} } = csp; return policies['script-src'] || policies['default-src'] || [] } } env () { return Object.assign( super.env(), { 'process.env.VUE_ENV': JSON.stringify('client'), 'process.browser': true, 'process.client': true, 'process.server': false, 'process.modern': false } ) } optimization () { const optimization = super.optimization(); const { splitChunks } = optimization; const { cacheGroups } = splitChunks; // 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 && cacheGroups.commons === undefined ) { cacheGroups.commons = { test: /node_modules[\\/](vue|vue-loader|vue-router|vuex|vue-meta|core-js|@babel\/runtime|axios|webpack|setimmediate|timers-browserify|process|regenerator-runtime|cookie|js-cookie|is-buffer|dotprop|url-polyfill|@nuxt[\\/]ufo|ufo|nuxt\.js)[\\/]/, chunks: 'all', name: true, priority: 10 }; } return optimization } minimizer () { const minimizer = super.minimizer(); const { optimizeCSS } = this.buildContext.buildOptions; // https://github.com/NMFR/optimize-css-assets-webpack-plugin // https://github.com/webpack-contrib/mini-css-extract-plugin#minimizing-for-production // TODO: Remove OptimizeCSSAssetsPlugin when upgrading to webpack 5 if (optimizeCSS) { minimizer.push(new OptimizeCSSAssetsPlugin__default['default'](Object.assign({}, optimizeCSS))); } return minimizer } alias () { const aliases = super.alias(); for (const p of this.buildContext.plugins) { if (!aliases[p.name]) { // Do not load server-side plugins on client-side aliases[p.name] = p.mode === 'server' ? './empty.js' : p.src; } } return aliases } plugins () { const plugins = super.plugins(); const { buildOptions, options: { appTemplatePath, buildDir, modern, render } } = this.buildContext; // Generate output HTML for SSR if (buildOptions.ssr) { plugins.push( new HtmlWebpackPlugin__default['default']({ filename: '../server/index.ssr.html', template: appTemplatePath, minify: buildOptions.html.minify, inject: false // Resources will be injected using bundleRenderer }) ); } plugins.push( new HtmlWebpackPlugin__default['default']({ filename: '../server/index.spa.html', template: appTemplatePath, minify: buildOptions.html.minify, inject: true }), new VueSSRClientPlugin({ filename: `../server/${this.name}.manifest.json` }), new webpack__default['default'].DefinePlugin(this.env()) ); if (this.dev) { // TODO: webpackHotUpdate is not defined: https://github.com/webpack/webpack/issues/6693 plugins.push(new webpack__default['default'].HotModuleReplacementPlugin()); } // Webpack Bundle Analyzer // https://github.com/webpack-contrib/webpack-bundle-analyzer if (!this.dev && buildOptions.analyze) { const statsDir = path__default['default'].resolve(buildDir, 'stats'); plugins.push(new BundleAnalyzer__default['default'].BundleAnalyzerPlugin(Object.assign({ analyzerMode: 'static', defaultSizes: 'gzip', generateStatsFile: true, openAnalyzer: !buildOptions.quiet, reportFilename: path__default['default'].resolve(statsDir, `${this.name}.html`), statsFilename: path__default['default'].resolve(statsDir, `${this.name}.json`) }, buildOptions.analyze))); } if (modern) { const scriptPolicy = this.getCspScriptPolicy(); const noUnsafeInline = scriptPolicy && !scriptPolicy.includes('\'unsafe-inline\''); plugins.push(new ModernModePlugin({ targetDir: path__default['default'].resolve(buildDir, 'dist', 'client'), isModernBuild: this.isModern, noUnsafeInline })); } if (render.crossorigin) { plugins.push(new CorsPlugin({ crossorigin: render.crossorigin })); } return plugins } config () { const config = super.config(); const { options: { router, buildDir }, buildOptions: { hotMiddleware, quiet, friendlyErrors } } = this.buildContext; const { client = {} } = hotMiddleware || {}; const { ansiColors, overlayStyles, ...options } = client; const hotMiddlewareClientOptions = { reload: true, timeout: 30000, ansiColors: JSON.stringify(ansiColors), overlayStyles: JSON.stringify(overlayStyles), path: `${router.base}/__webpack_hmr/${this.name}`.replace(/\/\//g, '/'), ...options, name: this.name }; const hotMiddlewareClientOptionsStr = querystring__default['default'].stringify(hotMiddlewareClientOptions); // Entry points config.entry = Object.assign({}, config.entry, { app: [path__default['default'].resolve(buildDir, 'client.js')] }); // Add HMR support if (this.dev) { config.entry.app.unshift( // https://github.com/webpack-contrib/webpack-hot-middleware/issues/53#issuecomment-162823945 this.resolveModule('eventsource-polyfill'), // https://github.com/glenjamin/webpack-hot-middleware#config `${this.resolveModule('webpack-hot-middleware/client')}?${hotMiddlewareClientOptionsStr}` ); } // Add friendly error plugin if (this.dev && !quiet && friendlyErrors) { config.plugins.push( new FriendlyErrorsWebpackPlugin__default['default']({ clearConsole: false, reporter: 'consola', logLevel: 'WARNING' }) ); } return config } } class WebpackModernConfig extends WebpackClientConfig { constructor (...args) { super(...args); this.name = 'modern'; this.isModern = true; } env () { return Object.assign(super.env(), { 'process.modern': true }) } } class VueSSRServerPlugin { constructor (options = {}) { this.options = Object.assign({ filename: null }, options); } apply (compiler) { validate(compiler); compiler.hooks.emit.tapAsync('vue-server-plugin', (compilation, cb) => { const stats = compilation.getStats().toJson(); const [entryName] = Object.keys(stats.entrypoints); const entryInfo = stats.entrypoints[entryName]; if (!entryInfo) { // #5553 return cb() } const entryAssets = entryInfo.assets.filter(isJS); if (entryAssets.length > 1) { throw new Error( 'Server-side bundle should have one single entry file. ' + 'Avoid using CommonsChunkPlugin in the server config.' ) } const [entry] = entryAssets; if (!entry || typeof entry !== 'string') { throw new Error( `Entry "${entryName}" not found. Did you specify the correct entry option?` ) } const bundle = { entry, files: {}, maps: {} }; stats.assets.forEach((asset) => { if (isJS(asset.name)) { const queryPart = extractQueryPartJS(asset.name); if (queryPart !== undefined) { bundle.files[asset.name] = asset.name.replace(queryPart, ''); } else { bundle.files[asset.name] = asset.name; } } else if (asset.name.match(/\.js\.map$/)) { bundle.maps[asset.name.replace(/\.map$/, '')] = asset.name; } else { // Do not emit non-js assets for server delete compilation.assets[asset.name]; } }); const src = JSON.stringify(bundle, null, 2); compilation.assets[this.options.filename] = { source: () => src, size: () => src.length }; cb(); }); } } const nativeFileExtensions = [ '.json', '.js' ]; class WebpackServerConfig extends WebpackBaseConfig { constructor (...args) { super(...args); this.name = 'server'; this.isServer = true; } get devtool () { return 'cheap-module-source-map' } get externalsAllowlist () { return [ this.isNonNativeImport.bind(this), ...this.normalizeTranspile() ] } /** * files *not* ending on js|json should be processed by webpack * * this might generate false-positives for imports like * - "someFile.umd" (actually requiring someFile.umd.js) * - "some.folder" (some.folder being a directory containing a package.json) */ isNonNativeImport (modulePath) { const extname = path__default['default'].extname(modulePath); return extname !== '' && !nativeFileExtensions.includes(extname) } env () { return Object.assign( super.env(), { 'process.env.VUE_ENV': JSON.stringify('server'), 'process.browser': false, 'process.client': false, 'process.server': true, 'process.modern': false } ) } optimization () { const { _minifyServer } = this.buildContext.buildOptions; return { splitChunks: false, minimizer: _minifyServer ? this.minimizer() : [] } } resolve () { const resolveConfig = super.resolve(); resolveConfig.resolve.mainFields = ['main', 'module']; return resolveConfig } alias () { const aliases = super.alias(); for (const p of this.buildContext.plugins) { if (!aliases[p.name]) { // Do not load client-side plugins on server-side aliases[p.name] = p.mode === 'client' ? './empty.js' : p.src; } } return aliases } plugins () { const plugins = super.plugins(); plugins.push( new VueSSRServerPlugin({ filename: `${this.name}.manifest.json` }), new webpack.DefinePlugin(this.env()) ); const { serverURLPolyfill } = this.buildContext.options.build; if (serverURLPolyfill) { plugins.push(new webpack.ProvidePlugin({ URL: [serverURLPolyfill, 'URL'], URLSearchParams: [serverURLPolyfill, 'URLSearchParams'] })); } return plugins } config () { const config = super.config(); Object.assign(config, { target: 'node', node: false, entry: Object.assign({}, config.entry, { app: [path__default['default'].resolve(this.buildContext.options.buildDir, 'server.js')] }), output: Object.assign({}, config.output, { filename: 'server.js', chunkFilename: '[name].js', libraryTarget: 'commonjs2' }), performance: { hints: false, maxEntrypointSize: Infinity, maxAssetSize: Infinity }, externals: [].concat(config.externals || []) }); // 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 (fs__default['default'].existsSync(dir)) { config.externals.push( nodeExternals__default['default']({ allowlist: this.externalsAllowlist, modulesDir: dir }) ); } }); } return config } } const WebpackConfigs = /*#__PURE__*/Object.freeze({ __proto__: null, client: WebpackClientConfig, modern: WebpackModernConfig, server: WebpackServerConfig }); const glob = pify__default['default'](Glob__default['default']); class WebpackBundler { constructor (buildContext) { this.buildContext = buildContext; // Class fields this.compilers = []; this.compilersWatching = []; this.devMiddleware = {}; this.hotMiddleware = {}; // Bind middleware to self this.middleware = this.middleware.bind(this); // Initialize shared MFS for dev if (this.buildContext.options.dev) { this.mfs = new AsyncMFS(); } } getWebpackConfig (name) { const Config = WebpackConfigs[name.toLowerCase()]; // eslint-disable-line import/namespace if (!Config) { throw new Error(`Unsupported webpack config ${name}`) } const config = new Config(this); return config.config() } async build () { const { options } = this.buildContext; const webpackConfigs = [ this.getWebpackConfig('Client') ]; if (options.modern) { webpackConfigs.push(this.getWebpackConfig('Modern')); } if (options.build.ssr) { webpackConfigs.push(this.getWebpackConfig('Server')); } await this.buildContext.nuxt.callHook('webpack:config', webpackConfigs); // Check styleResource existence const { styleResources } = this.buildContext.options.build; if (styleResources && Object.keys(styleResources).length) { consola__default['default'].warn( 'Using styleResources without the @nuxtjs/style-resources 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(utils.wrapArray(styleResources[ext]).map(async (p) => { const styleResourceFiles = await glob(path__default['default'].resolve(this.buildContext.options.rootDir, p)); if (!styleResourceFiles || styleResourceFiles.length === 0) { throw new Error(`Style Resource not found: ${p}`) } })); } } // Configure compilers this.compilers = webpackConfigs.map((config) => { const compiler = webpack__default['default'](config); // In dev, write files in memory FS if (options.dev) { compiler.outputFileSystem = this.mfs; } return compiler }); // Warm up perfLoader before build if (options.build.parallel) { consola__default['default'].info('Warming up worker pools'); PerfLoader.warmupAll({ dev: options.dev, resolveModule: id => utils.tryResolve(id, __filename) || id }); consola__default['default'].success('Worker pools ready'); } // Start Builds const runner = options.dev ? utils.parallel : utils.sequence; await runner(this.compilers, compiler => this.webpackCompile(compiler)); } async webpackCompile (compiler) { const { name } = compiler.options; const { nuxt, options } = this.buildContext; await nuxt.callHook('build:compile', { name, compiler }); // Load renderer resources after build compiler.hooks.done.tap('load-resources', async (stats) => { await nuxt.callHook('build:compiled', { name, compiler, stats }); // Reload renderer await nuxt.callHook('build:resources', this.mfs); }); // --- Dev Build --- if (options.dev) { // Client Build, watch is started by dev-middleware if (['client', 'modern'].includes(name)) { return new Promise((resolve, reject) => { compiler.hooks.done.tap('nuxt-dev', () => resolve()); return this.webpackDev(compiler) }) } // Server, build and watch for changes return new Promise((resolve, reject) => { const watching = compiler.watch(options.watchers.webpack, (err) => { if (err) { return reject(err) } resolve(); }); watching.close = pify__default['default'](watching.close); this.compilersWatching.push(watching); }) } // --- Production Build --- compiler.run = pify__default['default'](compiler.run); const stats = await compiler.run(); if (stats.hasErrors()) { // non-quiet mode: errors will be printed by webpack itself const error = new Error('Nuxt build error'); if (options.build.quiet === true) { error.stack = stats.toString('errors-only'); } throw error } // Await for renderer to load resources (programmatic, tests and generate) await nuxt.callHook('build:resources'); } async webpackDev (compiler) { consola__default['default'].debug('Creating webpack middleware...'); const { name } = compiler.options; const buildOptions = this.buildContext.options.build; const { client, ...hotMiddlewareOptions } = buildOptions.hotMiddleware || {}; compiler.options.watchOptions = this.buildContext.options.watchers.webpack; compiler.hooks.infrastructureLog.tap('webpack-dev-middleware-log', (name) => { if (name === 'webpack-dev-middleware') { return false } return undefined }); // Create webpack dev middleware this.devMiddleware[name] = pify__default['default']( webpackDevMiddleware__default['default']( compiler, { outputFileSystem: compiler.outputFileSystem, ...buildOptions.devMiddleware }) ); this.devMiddleware[name].close = pify__default['default'](this.devMiddleware[name].close); this.compilersWatching.push(this.devMiddleware[name].context.watching); this.hotMiddleware[name] = pify__default['default']( webpackHotMiddleware__default['default']( compiler, { log: false, heartbeat: 10000, path: `/__webpack_hmr/${name}`, ...hotMiddlewareOptions }) ); // Register devMiddleware on server await this.buildContext.nuxt.callHook('server:devMiddleware', this.middleware); } async middleware (req, res, next) { const name = utils.isModernRequest(req, this.buildContext.options.modern) ? 'modern' : 'client'; if (this.devMiddleware && this.devMiddleware[name]) { const { url } = req; req.url = req.originalUrl || req.url; await this.devMiddleware[name](req, res); req.url = url; } if (this.hotMiddleware && this.hotMiddleware[name]) { await this.hotMiddleware[name](req, res); } next(); } async unwatch () { await Promise.all(this.compilersWatching.map(watching => watching.close())); } async close () { if (this.__closed) { return } this.__closed = true; // Unwatch await this.unwatch(); // Stop webpack middleware for (const devMiddleware of Object.values(this.devMiddleware)) { await devMiddleware.close(); } // Cleanup MFS if (this.mfs) { delete this.mfs.data; delete this.mfs; } // Cleanup more resources delete this.compilers; delete this.compilersWatching; delete this.devMiddleware; delete this.hotMiddleware; } forGenerate () { this.buildContext.target = utils.TARGETS.static; } } exports.BundleBuilder = WebpackBundler;