/*!
 * @nuxt/webpack v2.15.8 (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;
