code:
const defaults = {
  clean: true,
  target: 'app',
  module: true,
  formats: 'commonjs,umd,umd-min'
}

const buildModes = {
  lib: 'library',
  wc: 'web component',
  'wc-async': 'web component (async)'
}

const modifyConfig = (config, fn) => {
  if (Array.isArray(config)) {
    config.forEach(c => fn(c))
  } else {
    fn(config)
  }
}

module.exports = (api, options) => {
  api.registerCommand('build', {
    description: 'build for production',
    usage: 'vue-cli-service build [options] [entry|pattern]',
    options: {
      '--mode': `specify env mode (default: production)`,
      '--dest': `specify output directory (default: ${options.outputDir})`,
      '--no-module': `build app without generating <script type="module"> chunks for modern browsers`,
      '--target': `app | lib | wc | wc-async (default: ${defaults.target})`,
      '--inline-vue': 'include the Vue module in the final bundle of library or web component target',
      '--formats': `list of output formats for library builds (default: ${defaults.formats})`,
      '--name': `name for lib or web-component mode (default: "name" in package.json or entry filename)`,
      '--filename': `file name for output, only usable for 'lib' target (default: value of --name)`,
      '--no-clean': `do not remove the dist directory contents before building the project`,
      '--report': `generate report.html to help analyze bundle content`,
      '--report-json': 'generate report.json to help analyze bundle content',
      '--skip-plugins': `comma-separated list of plugin names to skip for this run`,
      '--watch': `watch for changes`,
      '--stdin': `close when stdin ends`
    }
  }, async (args, rawArgs) => {
    for (const key in defaults) {
      if (args[key] == null) {
        args[key] = defaults[key]
      }
    }
    args.entry = args.entry || args._[0]
    if (args.target !== 'app') {
      args.entry = args.entry || 'src/App.vue'
    }

    process.env.VUE_CLI_BUILD_TARGET = args.target

    const { log, execa } = require('@vue/cli-shared-utils')
    const { allProjectTargetsSupportModule } = require('../../util/targets')

    let needsDifferentialLoading = args.target === 'app' && args.module
    if (allProjectTargetsSupportModule) {
      log(
        `All browser targets in the browserslist configuration have supported ES module.\n` +
        `Therefore we don't build two separate bundles for differential loading.\n`
      )
      needsDifferentialLoading = false
    }

    args.needsDifferentialLoading = needsDifferentialLoading
    if (!needsDifferentialLoading) {
      await build(args, api, options)
      return
    }

    process.env.VUE_CLI_MODERN_MODE = true
    if (!process.env.VUE_CLI_MODERN_BUILD) {
      // main-process for legacy build
      const legacyBuildArgs = { ...args, moduleBuild: false, keepAlive: true }
      await build(legacyBuildArgs, api, options)

      // spawn sub-process of self for modern build
      const cliBin = require('path').resolve(__dirname, '../../../bin/vue-cli-service.js')
      await execa('node', [cliBin, 'build', ...rawArgs], {
        stdio: 'inherit',
        env: {
          VUE_CLI_MODERN_BUILD: true
        }
      })
    } else {
      // sub-process for modern build
      const moduleBuildArgs = { ...args, moduleBuild: true, clean: false }
      await build(moduleBuildArgs, api, options)
    }
  })
}

async function build (args, api, options) {
  const fs = require('fs-extra')
  const path = require('path')
  const webpack = require('webpack')
  const { chalk } = require('@vue/cli-shared-utils')
  const formatStats = require('./formatStats')
  const validateWebpackConfig = require('../../util/validateWebpackConfig')
  const {
    log,
    done,
    info,
    logWithSpinner,
    stopSpinner
  } = require('@vue/cli-shared-utils')

  log()
  const mode = api.service.mode
  if (args.target === 'app') {
    const bundleTag = args.needsDifferentialLoading
      ? args.moduleBuild
        ? `module bundle `
        : `legacy bundle `
      : ``
    logWithSpinner(`Building ${bundleTag}for ${mode}...`)
  } else {
    const buildMode = buildModes[args.target]
    if (buildMode) {
      const additionalParams = buildMode === 'library' ? ` (${args.formats})` : ``
      logWithSpinner(`Building for ${mode} as ${buildMode}${additionalParams}...`)
    } else {
      throw new Error(`Unknown build target: ${args.target}`)
    }
  }

  if (args.dest) {
    // Override outputDir before resolving webpack config as config relies on it (#2327)
    options.outputDir = args.dest
  }

  const targetDir = api.resolve(options.outputDir)
  const isLegacyBuild = args.needsDifferentialLoading && !args.moduleBuild

  // resolve raw webpack config
  let webpackConfig
  if (args.target === 'lib') {
    webpackConfig = require('./resolveLibConfig')(api, args, options)
  } else if (
    args.target === 'wc' ||
    args.target === 'wc-async'
  ) {
    webpackConfig = require('./resolveWcConfig')(api, args, options)
  } else {
    webpackConfig = require('./resolveAppConfig')(api, args, options)
  }

  // check for common config errors
  validateWebpackConfig(webpackConfig, api, options, args.target)

  if (args.watch) {
    modifyConfig(webpackConfig, config => {
      config.watch = true
    })
  }

  if (args.stdin) {
    process.stdin.on('end', () => {
      process.exit(0)
    })
    process.stdin.resume()
  }

  // Expose advanced stats
  if (args.dashboard) {
    const DashboardPlugin = require('../../webpack/DashboardPlugin')
    modifyConfig(webpackConfig, config => {
      config.plugins.push(new DashboardPlugin({
        type: 'build',
        moduleBuild: args.moduleBuild,
        keepAlive: args.keepAlive
      }))
    })
  }

  if (args.report || args['report-json']) {
    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
    modifyConfig(webpackConfig, config => {
      const bundleName = args.target !== 'app'
        ? config.output.filename.replace(/\.js$/, '-')
        : isLegacyBuild ? 'legacy-' : ''
      config.plugins.push(new BundleAnalyzerPlugin({
        logLevel: 'warn',
        openAnalyzer: false,
        analyzerMode: args.report ? 'static' : 'disabled',
        reportFilename: `${bundleName}report.html`,
        statsFilename: `${bundleName}report.json`,
        generateStatsFile: !!args['report-json']
      }))
    })
  }

  if (args.clean) {
    await fs.emptyDir(targetDir)
  }

  return new Promise((resolve, reject) => {
    webpack(webpackConfig, (err, stats) => {
      stopSpinner(false)
      if (err) {
        return reject(err)
      }

      if (stats.hasErrors()) {
        return reject(new Error('Build failed with errors.'))
      }

      if (!args.silent) {
        const targetDirShort = path.relative(
          api.service.context,
          targetDir
        )
        log(formatStats(stats, targetDirShort, api))
        if (args.target === 'app' && !isLegacyBuild) {
          if (!args.watch) {
            done(`Build complete. The ${chalk.cyan(targetDirShort)} directory is ready to be deployed.`)
            info(`Check out deployment instructions at ${chalk.cyan(`https://cli.vuejs.org/guide/deployment.html`)}\n`)
          } else {
            done(`Build complete. Watching for changes...`)
          }
        }
      }

      // test-only signal
      if (process.env.VUE_CLI_TEST) {
        console.log('Build complete.')
      }

      resolve()
    })
  })
}

module.exports.defaultModes = {
  build: 'production'
}


code:
module.exports = (api, args, options) => {
  // respect inline entry
  if (args.entry && !options.pages) {
    api.configureWebpack(config => {
      config.entry = { app: api.resolve(args.entry) }
    })
  }

  const config = api.resolveChainableWebpackConfig()
  const targetDir = api.resolve(args.dest || options.outputDir)

  // respect inline build destination in copy plugin
  if (args.dest && config.plugins.has('copy')) {
    config.plugin('copy').tap(pluginArgs => {
      pluginArgs[0].patterns.to = targetDir
      return pluginArgs
    })
  }

  if (process.env.VUE_CLI_MODERN_MODE) {
    const ModernModePlugin = require('../../webpack/ModernModePlugin')
    const SafariNomoduleFixPlugin = require('../../webpack/SafariNomoduleFixPlugin')

    if (!args.moduleBuild) {
      // Inject plugin to extract build stats and write to disk
      config
        .plugin('modern-mode-legacy')
        .use(ModernModePlugin, [{
          targetDir,
          isModuleBuild: false
        }])
    } else {
      config
        .plugin('safari-nomodule-fix')
        .use(SafariNomoduleFixPlugin, [{
          // as we may generate an addition file asset (if Safari 10 fix is needed)
          // we need to provide the correct directory for that file to place in
          jsDirectory: require('../../util/getAssetPath')(options, 'js')
        }])

      // Inject plugin to read non-modern build stats and inject HTML
      config
        .plugin('modern-mode-modern')
        .use(ModernModePlugin, [{
          targetDir,
          isModuleBuild: true
        }])
    }
  }

  return api.resolveWebpackConfig(config)
}

license: mit


code:
const fs = require('fs')
const path = require('path')

module.exports = (api, { entry, name, formats, filename, 'inline-vue': inlineVue }, options) => {
  const { log, error } = require('@vue/cli-shared-utils')
  const abort = msg => {
    log()
    error(msg)
    process.exit(1)
  }

  const vueMajor = require('../../util/getVueMajor')(api.getCwd())

  const fullEntryPath = api.resolve(entry)

  if (!fs.existsSync(fullEntryPath)) {
    abort(
      `Failed to resolve lib entry: ${entry}${entry === `src/App.vue` ? ' (default)' : ''}. ` +
      `Make sure to specify the correct entry file.`
    )
  }

  const isVueEntry = /\.vue$/.test(entry)
  const libName = (
    name ||
    (
      api.service.pkg.name
        ? api.service.pkg.name.replace(/^@.+\//, '')
        : path.basename(entry).replace(/\.(jsx?|vue)$/, '')
    )
  )
  filename = filename || libName
  function genConfig (format, postfix = format, genHTML) {
    const config = api.resolveChainableWebpackConfig()

    const browserslist = require('browserslist')
    const targets = browserslist(undefined, { path: fullEntryPath })
    const supportsIE = targets.some(agent => agent.includes('ie'))

    const webpack = require('webpack')
    config.plugin('need-current-script-polyfill')
      .use(webpack.DefinePlugin, [{
        'process.env.NEED_CURRENTSCRIPT_POLYFILL': JSON.stringify(supportsIE)
      }])

    // adjust css output name so they write to the same file
    if (config.plugins.has('extract-css')) {
      config
        .plugin('extract-css')
          .tap(args => {
            args[0].filename = `${filename}.css`
            return args
          })
    }

    // only minify min entry
    if (!/\.min/.test(postfix)) {
      config.optimization.minimize(false)
    }

    // inject demo page for umd
    if (genHTML) {
      const template = isVueEntry ? 'demo-lib.html' : 'demo-lib-js.html'
      config
        .plugin('demo-html')
          .use(require('html-webpack-plugin'), [{
            template: path.resolve(__dirname, template),
            inject: false,
            filename: 'demo.html',
            libName,
            vueMajor,
            assetsFileName: filename,
            cssExtract: config.plugins.has('extract-css')
          }])
    }

    // resolve entry/output
    const entryName = `${filename}.${postfix}`
    config.resolve
      .alias
        .set('~entry', fullEntryPath)

    // set output target before user configureWebpack hooks are applied
    config.output.libraryTarget(format)

    // set entry/output after user configureWebpack hooks are applied
    const rawConfig = api.resolveWebpackConfig(config)

    let realEntry = require.resolve('./entry-lib.js')

    // avoid importing default if user entry file does not have default export
    if (!isVueEntry) {
      const entryContent = fs.readFileSync(fullEntryPath, 'utf-8')
      if (!/\b(export\s+default|export\s{[^}]+as\s+default)\b/.test(entryContent)) {
        realEntry = require.resolve('./entry-lib-no-default.js')
      }
    }

    // externalize Vue in case user imports it
    rawConfig.externals = [
      ...(Array.isArray(rawConfig.externals) ? rawConfig.externals : [rawConfig.externals]),
      {
        ...(inlineVue || {
          vue: {
            commonjs: 'vue',
            commonjs2: 'vue',
            root: 'Vue'
          }
        })
      }
    ].filter(Boolean)

    rawConfig.entry = {
      [entryName]: realEntry
    }

    rawConfig.output = Object.assign({
      library: libName,
      libraryExport: isVueEntry ? 'default' : undefined,
      libraryTarget: format,
      // preserve UDM header from webpack 3 until webpack provides either
      // libraryTarget: 'esm' or target: 'universal'
      // https://github.com/webpack/webpack/issues/6522
      // https://github.com/webpack/webpack/issues/6525
      globalObject: `(typeof self !== 'undefined' ? self : this)`
    }, rawConfig.output, {
      filename: `${entryName}.js`,
      chunkFilename: `${entryName}.[name].js`,
      // use dynamic publicPath so this can be deployed anywhere
      // the actual path will be determined at runtime by checking
      // document.currentScript.src.
      publicPath: ''
    })

    if (format === 'commonjs2') {
      // #6188
      delete rawConfig.output.library
    }

    return rawConfig
  }

  const configMap = {
    commonjs: genConfig('commonjs2', 'common'),
    umd: genConfig('umd', undefined, true),
    'umd-min': genConfig('umd', 'umd.min')
  }

  const formatArray = (formats + '').split(',')
  const configs = formatArray.map(format => configMap[format])
  if (configs.indexOf(undefined) !== -1) {
    const unknownFormats = formatArray.filter(f => configMap[f] === undefined).join(', ')
    abort(
      `Unknown library build formats: ${unknownFormats}`
    )
  }

  return configs
}


code:
const path = require('path')
const { resolveEntry, fileToComponentName } = require('./resolveWcEntry')

module.exports = (api, { target, entry, name, 'inline-vue': inlineVue }) => {
  // Disable CSS extraction and turn on CSS shadow mode for vue-style-loader
  process.env.VUE_CLI_CSS_SHADOW_MODE = true

  const { log, error } = require('@vue/cli-shared-utils')
  const abort = msg => {
    log()
    error(msg)
    process.exit(1)
  }

  const cwd = api.getCwd()
  const webpack = require('webpack')
  const vueMajor = require('../../util/getVueMajor')(cwd)
  if (vueMajor === 3) {
    abort(`Vue 3 support of the web component target is still under development.`)
  }

  const isAsync = /async/.test(target)

  // generate dynamic entry based on glob files
  const resolvedFiles = require('globby').sync(entry.split(','), { cwd: api.resolve('.') })

  if (!resolvedFiles.length) {
    abort(`entry pattern "${entry}" did not match any files.`)
  }
  let libName
  let prefix
  if (resolvedFiles.length === 1) {
    // in single mode, determine the lib name from filename
    libName = name || fileToComponentName('', resolvedFiles[0]).kebabName
    prefix = ''
    if (libName.indexOf('-') < 0) {
      abort(`--name must contain a hyphen when building a single web component.`)
    }
  } else {
    // multi mode
    libName = prefix = (name || api.service.pkg.name)
    if (!libName) {
      abort(`--name is required when building multiple web components.`)
    }
  }

  const dynamicEntry = resolveEntry(prefix, libName, resolvedFiles, isAsync)

  function genConfig (minify, genHTML) {
    const config = api.resolveChainableWebpackConfig()

    // make sure not to transpile wc-wrapper
    config.module
      .rule('js')
        .exclude
          .add(/vue-wc-wrapper/)

    // only minify min entry
    if (!minify) {
      config.optimization.minimize(false)
    }

    config
      .plugin('webpack-virtual-modules')
        .use(require('webpack-virtual-modules'), [{
          [dynamicEntry.filePath]: dynamicEntry.content
        }])

    config
      .plugin('web-component-options')
        .use(webpack.DefinePlugin, [{
          'process.env.CUSTOM_ELEMENT_NAME': JSON.stringify(libName)
        }])

    // enable shadow mode in vue-loader
    config.module
      .rule('vue')
        .use('vue-loader')
          .tap(options => {
            options.shadowMode = true
            return options
          })

    if (genHTML) {
      config
        .plugin('demo-html')
          .use(require('html-webpack-plugin'), [{
            template: path.resolve(__dirname, `./demo-wc.html`),
            inject: false,
            filename: 'demo.html',
            libName,
            vueMajor,
            components:
              prefix === ''
                ? [libName]
                : resolvedFiles.map(file => {
                  return fileToComponentName(prefix, file).kebabName
                })
          }])
    }

    // set entry/output last so it takes higher priority than user
    // configureWebpack hooks

    // set proxy entry for *.vue files
    config.resolve
      .alias
        .set('~root', api.resolve('.'))

    const rawConfig = api.resolveWebpackConfig(config)

    // externalize Vue in case user imports it
    rawConfig.externals = [
      ...(Array.isArray(rawConfig.externals) ? rawConfig.externals : [rawConfig.externals]),
      { ...(inlineVue || { vue: 'Vue' }) }
    ].filter(Boolean)

    const entryName = `${libName}${minify ? `.min` : ``}`
    rawConfig.entry = {
      [entryName]: dynamicEntry.filePath
    }

    Object.assign(rawConfig.output, {
      filename: `${entryName}.js`,
      chunkFilename: `${libName}.[name]${minify ? `.min` : ``}.js`,
      // use dynamic publicPath so this can be deployed anywhere
      // the actual path will be determined at runtime by checking
      // document.currentScript.src.
      publicPath: ''
    })

    // to ensure that multiple copies of async wc bundles can co-exist
    // on the same page.
    rawConfig.output.uniqueName = `vue-lib-${libName}`

    return rawConfig
  }

  return [
    genConfig(false, true),
    genConfig(true, false)
  ]
}


code:
const path = require('path')

const camelizeRE = /-(\w)/g
const camelize = str => {
  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
}

const hyphenateRE = /\B([A-Z])/g
const hyphenate = str => {
  return str.replace(hyphenateRE, '-$1').toLowerCase()
}

/**
 * Creates the script to add the component to the custom elements
 * @param {string} prefix The prefix for the component library
 * @param {string} component The component name for single entry builds, component file for multi-entry builds
 * @param {string} file The file for the component
 * @param {boolean} isAsync Whether to load component async or not
 */
const createElement = (prefix, component, file, isAsync) => {
  const { camelName, kebabName } = exports.fileToComponentName(prefix, component)

  return isAsync
    ? `window.customElements.define('${kebabName}', wrap(Vue, () => import('~root/${file}?shadow')))\n`
    : `import ${camelName} from '~root/${file}?shadow'\n` +
        `window.customElements.define('${kebabName}', wrap(Vue, ${camelName}))\n`
}

exports.fileToComponentName = (prefix, file) => {
  const basename = path.basename(file).replace(/\.(jsx?|vue)$/, '')
  const camelName = camelize(basename)
  const kebabName = `${prefix ? `${prefix}-` : ``}${hyphenate(basename)}`
  return {
    basename,
    camelName,
    kebabName
  }
}

exports.resolveEntry = (prefix, libName, files, isAsync) => {
  const filePath = path.resolve(__dirname, 'entry-wc.js')
  const elements =
    prefix === ''
      ? [createElement('', libName, files[0])]
      : files.map(file => createElement(prefix, file, file, isAsync)).join('\n')

  function resolveImportPath (mod) {
    return require.resolve(mod).replace(/\\/g, '\\\\')
  }

  const content = `
import './setPublicPath'
import Vue from 'vue'
import wrap from '@vue/web-component-wrapper'

// runtime shared by every component chunk
import '${resolveImportPath('css-loader/dist/runtime/api.js')}'
import '${resolveImportPath('vue-style-loader/lib/addStylesShadow')}'
import '${resolveImportPath('@vue/vue-loader-v15/lib/runtime/componentNormalizer')}'

${elements}`.trim()

  return {
    filePath: filePath,
    content: content
  }
}


code:
/* eslint-disable no-var */
// This file is imported into lib/wc client bundles.

if (typeof window !== 'undefined') {
  var currentScript = window.document.currentScript
  if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {
    var getCurrentScript = require('@soda/get-current-script')
    currentScript = getCurrentScript()

    // for backward compatibility, because previously we directly included the polyfill
    if (!('currentScript' in document)) {
      Object.defineProperty(document, 'currentScript', { get: getCurrentScript })
    }
  }

  var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
  if (src) {
    __webpack_public_path__ = src[1] // eslint-disable-line
  }
}

// Indicate to webpack that this file can be concatenated
export default null


code:
const { chalk } = require('@vue/cli-shared-utils')
const getPadLength = require('../util/getPadLength')

module.exports = (api, options) => {
  api.registerCommand('help', args => {
    const commandName = args._[0]
    if (!commandName) {
      logMainHelp()
    } else {
      logHelpForCommand(commandName, api.service.commands[commandName])
    }
  })

  function logMainHelp () {
    console.log(
      `\n  Usage: vue-cli-service <command> [options]\n` +
      `\n  Commands:\n`
    )
    const commands = api.service.commands
    const padLength = getPadLength(commands)
    for (const name in commands) {
      if (name !== 'help') {
        const opts = commands[name].opts || {}
        console.log(`    ${
          chalk.blue(name.padEnd(padLength))
        }${
          opts.description || ''
        }`)
      }
    }
    console.log(`\n  run ${
      chalk.green(`vue-cli-service help [command]`)
    } for usage of a specific command.\n`)
  }

  function logHelpForCommand (name, command) {
    if (!command) {
      console.log(chalk.red(`\n  command "${name}" does not exist.`))
    } else {
      const opts = command.opts || {}
      if (opts.usage) {
        console.log(`\n  Usage: ${opts.usage}`)
      }
      if (opts.options) {
        console.log(`\n  Options:\n`)
        const padLength = getPadLength(opts.options)
        for (const [flags, description] of Object.entries(opts.options)) {
          console.log(`    ${
            chalk.blue(flags.padEnd(padLength))
          }${
            description
          }`)
        }
      }
      if (opts.details) {
        console.log()
        console.log(opts.details.split('\n').map(line => `  ${line}`).join('\n'))
      }
      console.log()
    }
  }
}


code:
module.exports = (api, options) => {
  api.registerCommand(
    'inspect',
    {
      description: 'inspect internal webpack config',
      usage: 'vue-cli-service inspect [options] [...paths]',
      options: {
        '--mode': 'specify env mode (default: development)',
        '--rule <ruleName>': 'inspect a specific module rule',
        '--plugin <pluginName>': 'inspect a specific plugin',
        '--rules': 'list all module rule names',
        '--plugins': 'list all plugin names',
        '--verbose': 'show full function definitions in output',
        '--skip-plugins': 'comma-separated list of plugin names to skip for this run'
      }
    },
    args => {
      const { chalk, get } = require('@vue/cli-shared-utils')
      const { toString } = require('webpack-chain')
      const { highlight } = require('cli-highlight')
      const config = api.resolveWebpackConfig()
      const { _: paths, verbose } = args

      let res
      let hasUnnamedRule
      if (args.rule) {
        res = config.module.rules.find(r => r.__ruleNames[0] === args.rule)
      } else if (args.plugin) {
        res = config.plugins.find(p => p.__pluginName === args.plugin)
      } else if (args.rules) {
        res = config.module.rules.map(r => {
          const name = r.__ruleNames ? r.__ruleNames[0] : 'Nameless Rule (*)'

          hasUnnamedRule = hasUnnamedRule || !r.__ruleNames

          return name
        })
      } else if (args.plugins) {
        res = config.plugins.map(p => p.__pluginName || p.constructor.name)
      } else if (paths.length > 1) {
        res = {}
        paths.forEach(path => {
          res[path] = get(config, path)
        })
      } else if (paths.length === 1) {
        res = get(config, paths[0])
      } else {
        res = config
      }

      const output = toString(res, { verbose })
      console.log(highlight(output, { language: 'js' }))

      // Log explanation for Nameless Rules
      if (hasUnnamedRule) {
        console.log(`--- ${chalk.green('Footnotes')} ---`)
        console.log(`*: ${chalk.green(
          'Nameless Rules'
        )} were added through the ${chalk.green(
          'configureWebpack()'
        )} API (possibly by a plugin) instead of ${chalk.green(
          'chainWebpack()'
        )} (recommended).
    You can run ${chalk.green(
    'vue-cli-service inspect'
  )} without any arguments to inspect the full config and read these rules' config.`)
      }
    }
  )
}

module.exports.defaultModes = {
  inspect: 'development'
}


code:
const {
  info,
  error,
  hasProjectYarn,
  hasProjectPnpm,
  IpcMessenger
} = require('@vue/cli-shared-utils')
const getBaseUrl = require('../util/getBaseUrl')

const defaults = {
  host: '0.0.0.0',
  port: 8080,
  https: false
}

/** @type {import('@vue/cli-service').ServicePlugin} */
module.exports = (api, options) => {
  const baseUrl = getBaseUrl(options)
  api.registerCommand('serve', {
    description: 'start development server',
    usage: 'vue-cli-service serve [options] [entry]',
    options: {
      '--open': `open browser on server start`,
      '--copy': `copy url to clipboard on server start`,
      '--stdin': `close when stdin ends`,
      '--mode': `specify env mode (default: development)`,
      '--host': `specify host (default: ${defaults.host})`,
      '--port': `specify port (default: ${defaults.port})`,
      '--https': `use https (default: ${defaults.https})`,
      '--public': `specify the public network URL for the HMR client`,
      '--skip-plugins': `comma-separated list of plugin names to skip for this run`
    }
  }, async function serve (args) {
    info('Starting development server...')

    // although this is primarily a dev server, it is possible that we
    // are running it in a mode with a production env, e.g. in E2E tests.
    const isInContainer = checkInContainer()
    const isProduction = process.env.NODE_ENV === 'production'

    const { chalk } = require('@vue/cli-shared-utils')
    const webpack = require('webpack')
    const WebpackDevServer = require('webpack-dev-server')
    const portfinder = require('portfinder')
    const prepareURLs = require('../util/prepareURLs')
    const prepareProxy = require('../util/prepareProxy')
    const launchEditorMiddleware = require('launch-editor-middleware')
    const validateWebpackConfig = require('../util/validateWebpackConfig')
    const isAbsoluteUrl = require('../util/isAbsoluteUrl')

    // configs that only matters for dev server
    api.chainWebpack(webpackConfig => {
      if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') {
        if (!webpackConfig.get('devtool')) {
          webpackConfig
            .devtool('eval-cheap-module-source-map')
        }

        // https://github.com/webpack/webpack/issues/6642
        // https://github.com/vuejs/vue-cli/issues/3539
        webpackConfig
          .output
            .globalObject(`(typeof self !== 'undefined' ? self : this)`)

        if (
          !process.env.VUE_CLI_TEST &&
          (!options.devServer.client ||
            options.devServer.client.progress !== false)
        ) {
          // the default progress plugin won't show progress due to infrastructreLogging.level
          webpackConfig
            .plugin('progress')
            .use(require('progress-webpack-plugin'))
        }
      }
    })

    // resolve webpack config
    const webpackConfig = api.resolveWebpackConfig()

    // check for common config errors
    validateWebpackConfig(webpackConfig, api, options)

    // load user devServer options with higher priority than devServer
    // in webpack config
    const projectDevServerOptions = Object.assign(
      webpackConfig.devServer || {},
      options.devServer
    )

    // expose advanced stats
    if (args.dashboard) {
      const DashboardPlugin = require('../webpack/DashboardPlugin')
      webpackConfig.plugins.push(new DashboardPlugin({
        type: 'serve'
      }))
    }

    // entry arg
    const entry = args._[0]
    if (entry) {
      webpackConfig.entry = {
        app: api.resolve(entry)
      }
    }

    // resolve server options
    const modesUseHttps = ['https', 'http2']
    const serversUseHttps = ['https', 'spdy']
    const optionsUseHttps = modesUseHttps.some(modeName => !!projectDevServerOptions[modeName]) ||
      (typeof projectDevServerOptions.server === 'string' && serversUseHttps.includes(projectDevServerOptions.server)) ||
      (typeof projectDevServerOptions.server === 'object' && projectDevServerOptions.server !== null && serversUseHttps.includes(projectDevServerOptions.server.type))
    const useHttps = args.https || optionsUseHttps || defaults.https
    const protocol = useHttps ? 'https' : 'http'
    const host = args.host || process.env.HOST || projectDevServerOptions.host || defaults.host
    portfinder.basePort = args.port || process.env.PORT || projectDevServerOptions.port || defaults.port
    const port = await portfinder.getPortPromise()
    const rawPublicUrl = args.public || projectDevServerOptions.public
    const publicUrl = rawPublicUrl
      ? /^[a-zA-Z]+:\/\//.test(rawPublicUrl)
        ? rawPublicUrl
        : `${protocol}://${rawPublicUrl}`
      : null
    const publicHost = publicUrl ? /^[a-zA-Z]+:\/\/([^/?#]+)/.exec(publicUrl)[1] : undefined

    const urls = prepareURLs(
      protocol,
      host,
      port,
      isAbsoluteUrl(baseUrl) ? '/' : baseUrl
    )
    const localUrlForBrowser = publicUrl || urls.localUrlForBrowser

    const proxySettings = prepareProxy(
      projectDevServerOptions.proxy,
      api.resolve('public')
    )

    // inject dev & hot-reload middleware entries
    let webSocketURL
    if (!isProduction) {
      if (publicHost) {
        // explicitly configured via devServer.public
        webSocketURL = {
          protocol: protocol === 'https' ? 'wss' : 'ws',
          hostname: publicHost,
          port
        }
      } else if (isInContainer) {
        // can't infer public network url if inside a container
        // infer it from the browser instead
        webSocketURL = 'auto://0.0.0.0:0/ws'
      } else {
        // otherwise infer the url from the config
        webSocketURL = {
          protocol: protocol === 'https' ? 'wss' : 'ws',
          hostname: urls.lanUrlForConfig || 'localhost',
          port
        }
      }

      if (process.env.APPVEYOR) {
        webpackConfig.plugins.push(
          new webpack.EntryPlugin(__dirname, 'webpack/hot/poll?500', { name: undefined })
        )
      }
    }

    const { projectTargets } = require('../util/targets')
    const supportsIE = !!projectTargets
    if (supportsIE) {
      webpackConfig.plugins.push(
        // must use undefined as name,
        // to avoid dev server establishing an extra ws connection for the new entry
        new webpack.EntryPlugin(__dirname, 'whatwg-fetch', { name: undefined })
      )
    }

    // fixme: temporary fix to suppress dev server logging
    // should be more robust to show necessary info but not duplicate errors
    webpackConfig.infrastructureLogging = { ...webpackConfig.infrastructureLogging, level: 'none' }
    webpackConfig.stats = 'errors-only'

    // create compiler
    const compiler = webpack(webpackConfig)

    // handle compiler error
    compiler.hooks.failed.tap('vue-cli-service serve', msg => {
      error(msg)
      process.exit(1)
    })

    // create server
    const server = new WebpackDevServer(Object.assign({
      historyApiFallback: {
        disableDotRule: true,
        htmlAcceptHeaders: [
          'text/html',
          'application/xhtml+xml'
        ],
        rewrites: genHistoryApiFallbackRewrites(baseUrl, options.pages)
      },
      hot: !isProduction
    }, projectDevServerOptions, {
      host,
      port,

      server: {
        type: protocol,
        ...(typeof projectDevServerOptions.server === 'object'
          ? projectDevServerOptions.server
          : {})
      },

      proxy: proxySettings,

      static: {
        directory: api.resolve('public'),
        publicPath: options.publicPath,
        watch: !isProduction,

        ...projectDevServerOptions.static
      },

      client: {
        webSocketURL,

        logging: 'none',
        overlay: isProduction // TODO disable this
          ? false
          : { warnings: false, errors: true },
        progress: !process.env.VUE_CLI_TEST,

        ...projectDevServerOptions.client
      },

      open: args.open || projectDevServerOptions.open,
      setupExitSignals: true,

      setupMiddlewares (middlewares, devServer) {
        // launch editor support.
        // this works with vue-devtools & @vue/cli-overlay
        devServer.app.use('/__open-in-editor', launchEditorMiddleware(() => console.log(
          `To specify an editor, specify the EDITOR env variable or ` +
          `add "editor" field to your Vue project config.\n`
        )))

        // allow other plugins to register middlewares, e.g. PWA
        // todo: migrate to the new API interface
        api.service.devServerConfigFns.forEach(fn => fn(devServer.app, devServer))

        if (projectDevServerOptions.setupMiddlewares) {
          return projectDevServerOptions.setupMiddlewares(middlewares, devServer)
        }

        return middlewares
      }
    }), compiler)

    if (args.stdin) {
      process.stdin.on('end', () => {
        server.stopCallback(() => {
          process.exit(0)
        })
      })

      process.stdin.resume()
    }

    // on appveyor, killing the process with SIGTERM causes execa to
    // throw error
    if (process.env.VUE_CLI_TEST) {
      process.stdin.on('data', data => {
        if (data.toString() === 'close') {
          console.log('got close signal!')
          server.stopCallback(() => {
            process.exit(0)
          })
        }
      })
    }

    return new Promise((resolve, reject) => {
      // log instructions & open browser on first compilation complete
      let isFirstCompile = true
      compiler.hooks.done.tap('vue-cli-service serve', stats => {
        if (stats.hasErrors()) {
          return
        }

        let copied = ''
        if (isFirstCompile && args.copy) {
          try {
            require('clipboardy').writeSync(localUrlForBrowser)
            copied = chalk.dim('(copied to clipboard)')
          } catch (_) {
            /* catch exception if copy to clipboard isn't supported (e.g. WSL), see issue #3476 */
          }
        }

        const networkUrl = publicUrl
          ? publicUrl.replace(/([^/])$/, '$1/')
          : urls.lanUrlForTerminal

        console.log()
        console.log(`  App running at:`)
        console.log(`  - Local:   ${chalk.cyan(urls.localUrlForTerminal)} ${copied}`)
        if (!isInContainer) {
          console.log(`  - Network: ${chalk.cyan(networkUrl)}`)
        } else {
          console.log()
          console.log(chalk.yellow(`  It seems you are running Vue CLI inside a container.`))
          if (!publicUrl && options.publicPath && options.publicPath !== '/') {
            console.log()
            console.log(chalk.yellow(`  Since you are using a non-root publicPath, the hot-reload socket`))
            console.log(chalk.yellow(`  will not be able to infer the correct URL to connect. You should`))
            console.log(chalk.yellow(`  explicitly specify the URL via ${chalk.blue(`devServer.public`)}.`))
            console.log()
          }
          console.log(chalk.yellow(`  Access the dev server via ${chalk.cyan(
            `${protocol}://localhost:<your container's external mapped port>${options.publicPath}`
          )}`))
        }
        console.log()

        if (isFirstCompile) {
          isFirstCompile = false

          if (!isProduction) {
            const buildCommand = hasProjectYarn(api.getCwd()) ? `yarn build` : hasProjectPnpm(api.getCwd()) ? `pnpm run build` : `npm run build`
            console.log(`  Note that the development build is not optimized.`)
            console.log(`  To create a production build, run ${chalk.cyan(buildCommand)}.`)
          } else {
            console.log(`  App is served in production mode.`)
            console.log(`  Note this is for preview or E2E testing only.`)
          }
          console.log()

          // Send final app URL
          if (args.dashboard) {
            const ipc = new IpcMessenger()
            ipc.send({
              vueServe: {
                url: localUrlForBrowser
              }
            })
          }

          // resolve returned Promise
          // so other commands can do api.service.run('serve').then(...)
          resolve({
            server,
            url: localUrlForBrowser
          })
        } else if (process.env.VUE_CLI_TEST) {
          // signal for test to check HMR
          console.log('App updated')
        }
      })

      server.start().catch(err => reject(err))
    })
  })
}

// https://stackoverflow.com/a/20012536
function checkInContainer () {
  if ('CODESANDBOX_SSE' in process.env) {
    return true
  }
  const fs = require('fs')
  if (fs.existsSync(`/proc/1/cgroup`)) {
    const content = fs.readFileSync(`/proc/1/cgroup`, 'utf-8')
    return /:\/(lxc|docker|kubepods(\.slice)?)\//.test(content)
  }
}

function genHistoryApiFallbackRewrites (baseUrl, pages = {}) {
  const path = require('path')
  const multiPageRewrites = Object
    .keys(pages)
    // sort by length in reversed order to avoid overrides
    // eg. 'page11' should appear in front of 'page1'
    .sort((a, b) => b.length - a.length)
    .map(name => ({
      from: new RegExp(`^/${name}`),
      to: path.posix.join(baseUrl, pages[name].filename || `${name}.html`)
    }))
  return [
    ...multiPageRewrites,
    { from: /./, to: path.posix.join(baseUrl, 'index.html') }
  ]
}

module.exports.defaultModes = {
  serve: 'development'
}


code:
// config that are specific to --target app
const fs = require('fs')
const path = require('path')

// ensure the filename passed to html-webpack-plugin is a relative path
// because it cannot correctly handle absolute paths
function ensureRelative (outputDir, _path) {
  if (path.isAbsolute(_path)) {
    return path.relative(outputDir, _path)
  } else {
    return _path
  }
}

module.exports = (api, options) => {
  api.chainWebpack(webpackConfig => {
    // only apply when there's no alternative target
    if (process.env.VUE_CLI_BUILD_TARGET && process.env.VUE_CLI_BUILD_TARGET !== 'app') {
      return
    }

    const isProd = process.env.NODE_ENV === 'production'
    const isLegacyBundle = process.env.VUE_CLI_MODERN_MODE && !process.env.VUE_CLI_MODERN_BUILD
    const outputDir = api.resolve(options.outputDir)

    const getAssetPath = require('../util/getAssetPath')
    const outputFilename = getAssetPath(
      options,
      `js/[name]${isLegacyBundle ? `-legacy` : ``}${isProd && options.filenameHashing ? '.[contenthash:8]' : ''}.js`
    )
    webpackConfig
      .output
        .filename(outputFilename)
        .chunkFilename(outputFilename)

    // FIXME: a temporary workaround to get accurate contenthash in `applyLegacy`
    // Should use a better fix per discussions at <https://github.com/jantimon/html-webpack-plugin/issues/1554#issuecomment-753653580>
    webpackConfig.optimization
      .set('realContentHash', false)

    // code splitting
    if (process.env.NODE_ENV !== 'test') {
      webpackConfig.optimization.splitChunks({
        cacheGroups: {
          defaultVendors: {
            name: `chunk-vendors`,
            test: /[\\/]node_modules[\\/]/,
            priority: -10,
            chunks: 'initial'
          },
          common: {
            name: `chunk-common`,
            minChunks: 2,
            priority: -20,
            chunks: 'initial',
            reuseExistingChunk: true
          }
        }
      })
    }

    // HTML plugin
    const resolveClientEnv = require('../util/resolveClientEnv')

    const htmlOptions = {
      title: api.service.pkg.name,
      scriptLoading: 'defer',
      templateParameters: (compilation, assets, assetTags, pluginOptions) => {
        // enhance html-webpack-plugin's built in template params
        return Object.assign({
          compilation: compilation,
          webpackConfig: compilation.options,
          htmlWebpackPlugin: {
            tags: assetTags,
            files: assets,
            options: pluginOptions
          }
        }, resolveClientEnv(options, true /* raw */))
      }
    }

    // handle indexPath
    if (options.indexPath !== 'index.html') {
      // why not set filename for html-webpack-plugin?
      // 1. It cannot handle absolute paths
      // 2. Relative paths causes incorrect SW manifest to be generated (#2007)
      webpackConfig
        .plugin('move-index')
        .use(require('../webpack/MovePlugin'), [
          path.resolve(outputDir, 'index.html'),
          path.resolve(outputDir, options.indexPath)
        ])
    }

    // resolve HTML file(s)
    const HTMLPlugin = require('html-webpack-plugin')
    // const PreloadPlugin = require('@vue/preload-webpack-plugin')
    const multiPageConfig = options.pages
    const htmlPath = api.resolve('public/index.html')
    const defaultHtmlPath = path.resolve(__dirname, 'index-default.html')
    const publicCopyIgnore = ['**/.DS_Store']

    if (!multiPageConfig) {
      // default, single page setup.
      htmlOptions.template = fs.existsSync(htmlPath)
        ? htmlPath
        : defaultHtmlPath

      publicCopyIgnore.push(api.resolve(htmlOptions.template).replace(/\\/g, '/'))

      webpackConfig
        .plugin('html')
          .use(HTMLPlugin, [htmlOptions])

      // FIXME: need to test out preload plugin's compatibility with html-webpack-plugin 4/5
      // if (!isLegacyBundle) {
      //   // inject preload/prefetch to HTML
      //   webpackConfig
      //     .plugin('preload')
      //       .use(PreloadPlugin, [{
      //         rel: 'preload',
      //         include: 'initial',
      //         fileBlacklist: [/\.map$/, /hot-update\.js$/]
      //       }])

      //   webpackConfig
      //     .plugin('prefetch')
      //       .use(PreloadPlugin, [{
      //         rel: 'prefetch',
      //         include: 'asyncChunks'
      //       }])
      // }
    } else {
      // multi-page setup
      webpackConfig.entryPoints.clear()

      const pages = Object.keys(multiPageConfig)
      const normalizePageConfig = c => typeof c === 'string' ? { entry: c } : c

      pages.forEach(name => {
        const pageConfig = normalizePageConfig(multiPageConfig[name])
        const {
          entry,
          template = `public/${name}.html`,
          filename = `${name}.html`,
          chunks = ['chunk-vendors', 'chunk-common', name]
        } = pageConfig

        // Currently Cypress v3.1.0 comes with a very old version of Node,
        // which does not support object rest syntax.
        // (https://github.com/cypress-io/cypress/issues/2253)
        // So here we have to extract the customHtmlOptions manually.
        const customHtmlOptions = {}
        for (const key in pageConfig) {
          if (
            !['entry', 'template', 'filename', 'chunks'].includes(key)
          ) {
            customHtmlOptions[key] = pageConfig[key]
          }
        }

        // inject entry
        const entries = Array.isArray(entry) ? entry : [entry]
        webpackConfig.entry(name).merge(entries.map(e => api.resolve(e)))

        // trim inline loader
        // * See https://github.com/jantimon/html-webpack-plugin/blob/master/docs/template-option.md#2-setting-a-loader-directly-for-the-template
        const templateWithoutLoader = template.replace(/^.+!/, '').replace(/\?.+$/, '')

        // resolve page index template
        const hasDedicatedTemplate = fs.existsSync(api.resolve(templateWithoutLoader))
        const templatePath = hasDedicatedTemplate
          ? template
          : fs.existsSync(htmlPath)
            ? htmlPath
            : defaultHtmlPath

        publicCopyIgnore.push(api.resolve(templateWithoutLoader).replace(/\\/g, '/'))

        // inject html plugin for the page
        const pageHtmlOptions = Object.assign(
          {},
          htmlOptions,
          {
            chunks,
            template: templatePath,
            filename: ensureRelative(outputDir, filename)
          },
          customHtmlOptions
        )

        webpackConfig
          .plugin(`html-${name}`)
            .use(HTMLPlugin, [pageHtmlOptions])
      })

      // FIXME: preload plugin is not compatible with webpack 5 / html-webpack-plugin 4 yet
      // if (!isLegacyBundle) {
      //   pages.forEach(name => {
      //     const filename = ensureRelative(
      //       outputDir,
      //       normalizePageConfig(multiPageConfig[name]).filename || `${name}.html`
      //     )
      //     webpackConfig
      //       .plugin(`preload-${name}`)
      //         .use(PreloadPlugin, [{
      //           rel: 'preload',
      //           includeHtmlNames: [filename],
      //           include: {
      //             type: 'initial',
      //             entries: [name]
      //           },
      //           fileBlacklist: [/\.map$/, /hot-update\.js$/]
      //         }])

      //     webpackConfig
      //       .plugin(`prefetch-${name}`)
      //         .use(PreloadPlugin, [{
      //           rel: 'prefetch',
      //           includeHtmlNames: [filename],
      //           include: {
      //             type: 'asyncChunks',
      //             entries: [name]
      //           }
      //         }])
      //   })
      // }
    }

    // CORS and Subresource Integrity
    if (options.crossorigin != null || options.integrity) {
      webpackConfig
        .plugin('cors')
          .use(require('../webpack/CorsPlugin'), [{
            crossorigin: options.crossorigin,
            integrity: options.integrity,
            publicPath: options.publicPath
          }])
    }

    // copy static assets in public/
    const publicDir = api.resolve('public')
    const CopyWebpackPlugin = require('copy-webpack-plugin')
    const PlaceholderPlugin = class PlaceholderPlugin { apply () {} }

    const copyOptions = {
      patterns: [{
        from: publicDir,
        to: outputDir,
        toType: 'dir',
        noErrorOnMissing: true,
        globOptions: {
          ignore: publicCopyIgnore
        },
        info: {
          minimized: true
        }
      }]
    }

    if (fs.existsSync(publicDir)) {
      if (isLegacyBundle) {
        webpackConfig.plugin('copy').use(PlaceholderPlugin, [copyOptions])
      } else {
        webpackConfig.plugin('copy').use(CopyWebpackPlugin, [copyOptions])
      }
    }
  })
}


code:
/** @type {import('@vue/cli-service').ServicePlugin} */
module.exports = (api, options) => {
  const getAssetPath = require('../util/getAssetPath')

  const genAssetSubPath = dir => {
    return getAssetPath(
      options,
      `${dir}/[name]${options.filenameHashing ? '.[hash:8]' : ''}[ext]`
    )
  }

  api.chainWebpack(webpackConfig => {
    webpackConfig.module
    .rule('svg')
      .test(/\.(svg)(\?.*)?$/)
      // do not base64-inline SVGs.
      // https://github.com/facebookincubator/create-react-app/pull/1180
      .set('type', 'asset/resource')
      .set('generator', {
        filename: genAssetSubPath('img')
      })

    webpackConfig.module
      .rule('images')
        .test(/\.(png|jpe?g|gif|webp|avif)(\?.*)?$/)
        .set('type', 'asset')
        .set('generator', {
          filename: genAssetSubPath('img')
        })

    webpackConfig.module
      .rule('media')
        .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
        .set('type', 'asset')
        .set('generator', {
          filename: genAssetSubPath('media')
        })

    webpackConfig.module
      .rule('fonts')
        .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
        .set('type', 'asset')
        .set('generator', {
          filename: genAssetSubPath('fonts')
        })
  })
}


code:
const path = require('path')

/** @type {import('@vue/cli-service').ServicePlugin} */
module.exports = (api, options) => {
  const cwd = api.getCwd()
  const webpack = require('webpack')
  const vueMajor = require('../util/getVueMajor')(cwd)

  api.chainWebpack(webpackConfig => {
    const isLegacyBundle = process.env.VUE_CLI_MODERN_MODE && !process.env.VUE_CLI_MODERN_BUILD
    const resolveLocal = require('../util/resolveLocal')

    // https://github.com/webpack/webpack/issues/14532#issuecomment-947525539
    webpackConfig.output.set('hashFunction', 'xxhash64')

    // https://github.com/webpack/webpack/issues/11467#issuecomment-691873586
    webpackConfig.module
      .rule('esm')
        .test(/\.m?jsx?$/)
        .resolve.set('fullySpecified', false)

    webpackConfig
      .mode('development')
      .context(api.service.context)
      .entry('app')
        .add('./src/main.js')
        .end()
      .output
        .path(api.resolve(options.outputDir))
        .filename(isLegacyBundle ? '[name]-legacy.js' : '[name].js')
        .publicPath(options.publicPath)

    webpackConfig.resolve
      .extensions
        .merge(['.mjs', '.js', '.jsx', '.vue', '.json', '.wasm'])
        .end()
      .modules
        .add('node_modules')
        .add(api.resolve('node_modules'))
        .add(resolveLocal('node_modules'))
        .end()
      .alias
        .set('@', api.resolve('src'))

    webpackConfig.resolveLoader
      .modules
        .add('node_modules')
        .add(api.resolve('node_modules'))
        .add(resolveLocal('node_modules'))

    webpackConfig.module
      .noParse(/^(vue|vue-router|vuex|vuex-router-sync)$/)

    // js is handled by cli-plugin-babel ---------------------------------------

    // vue-loader --------------------------------------------------------------
    let cacheLoaderPath
    try {
      cacheLoaderPath = require.resolve('cache-loader')
    } catch (e) {}

    if (vueMajor === 2) {
      // for Vue 2 projects
      const partialIdentifier = {
        'vue-loader': require('@vue/vue-loader-v15/package.json').version,
        '@vue/component-compiler-utils': require('@vue/component-compiler-utils/package.json').version
      }

      try {
        partialIdentifier['vue-template-compiler'] = require('vue-template-compiler/package.json').version
      } catch (e) {
        // For Vue 2.7 projects, `vue-template-compiler` is not required
      }

      const vueLoaderCacheConfig = api.genCacheConfig('vue-loader', partialIdentifier)

      webpackConfig.resolve
        .alias
          .set(
            'vue$',
            options.runtimeCompiler
              ? 'vue/dist/vue.esm.js'
              : 'vue/dist/vue.runtime.esm.js'
          )

      if (cacheLoaderPath) {
        webpackConfig.module
          .rule('vue')
            .test(/\.vue$/)
            .use('cache-loader')
              .loader(cacheLoaderPath)
              .options(vueLoaderCacheConfig)
      }

      webpackConfig.module
        .rule('vue')
          .test(/\.vue$/)
          .use('vue-loader')
            .loader(require.resolve('@vue/vue-loader-v15'))
            .options(Object.assign({
              compilerOptions: {
                whitespace: 'condense'
              }
            }, cacheLoaderPath ? vueLoaderCacheConfig : {}))

      webpackConfig
        .plugin('vue-loader')
          .use(require('@vue/vue-loader-v15').VueLoaderPlugin)

      // some plugins may implicitly relies on the `vue-loader` dependency path name
      // such as vue-cli-plugin-apollo
      // <https://github.com/Akryum/vue-cli-plugin-apollo/blob/d9fe48c61cc19db88fef4e4aa5e49b31aa0c44b7/index.js#L88>
      // so we need a hotfix for that
      webpackConfig
        .resolveLoader
          .modules
            .prepend(path.resolve(__dirname, './vue-loader-v15-resolve-compat'))
    } else if (vueMajor === 3) {
      // for Vue 3 projects
      const vueLoaderCacheConfig = api.genCacheConfig('vue-loader', {
        'vue-loader': require('vue-loader/package.json').version
      })

      webpackConfig.resolve
        .alias
          .set(
            'vue$',
            options.runtimeCompiler
              ? 'vue/dist/vue.esm-bundler.js'
              : 'vue/dist/vue.runtime.esm-bundler.js'
          )

      if (cacheLoaderPath) {
        webpackConfig.module
          .rule('vue')
            .test(/\.vue$/)
            .use('cache-loader')
              .loader(cacheLoaderPath)
              .options(vueLoaderCacheConfig)
      }

      webpackConfig.module
        .rule('vue')
          .test(/\.vue$/)
          .use('vue-loader')
            .loader(require.resolve('vue-loader'))
            .options({
              ...vueLoaderCacheConfig,
              babelParserPlugins: ['jsx', 'classProperties', 'decorators-legacy']
            })

      webpackConfig
        .plugin('vue-loader')
          .use(require('vue-loader').VueLoaderPlugin)

      // feature flags <http://link.vuejs.org/feature-flags>
      webpackConfig
        .plugin('feature-flags')
          .use(webpack.DefinePlugin, [{
            __VUE_OPTIONS_API__: 'true',
            __VUE_PROD_DEVTOOLS__: 'false'
          }])
    }

    // https://github.com/vuejs/vue-loader/issues/1435#issuecomment-869074949
    webpackConfig.module
      .rule('vue-style')
        .test(/\.vue$/)
          .resourceQuery(/type=style/)
            .sideEffects(true)

    // Other common pre-processors ---------------------------------------------
    const maybeResolve = name => {
      try {
        return require.resolve(name)
      } catch (error) {
        return name
      }
    }

    webpackConfig.module
      .rule('pug')
        .test(/\.pug$/)
          .oneOf('pug-vue')
            .resourceQuery(/vue/)
            .use('pug-plain-loader')
              .loader(maybeResolve('pug-plain-loader'))
              .end()
            .end()
          .oneOf('pug-template')
            .use('raw')
              .loader(maybeResolve('raw-loader'))
              .end()
            .use('pug-plain-loader')
              .loader(maybeResolve('pug-plain-loader'))
              .end()
            .end()

    const resolveClientEnv = require('../util/resolveClientEnv')
    webpackConfig
      .plugin('define')
        .use(webpack.DefinePlugin, [
          resolveClientEnv(options)
        ])

    webpackConfig
      .plugin('case-sensitive-paths')
        .use(require('case-sensitive-paths-webpack-plugin'))

    // friendly error plugin displays very confusing errors when webpack
    // fails to resolve a loader, so we provide custom handlers to improve it
    const { transformer, formatter } = require('../util/resolveLoaderError')
    webpackConfig
      .plugin('friendly-errors')
        .use(require('@soda/friendly-errors-webpack-plugin'), [{
          additionalTransformers: [transformer],
          additionalFormatters: [formatter]
        }])

    const TerserPlugin = require('terser-webpack-plugin')
    const terserOptions = require('./terserOptions')
    webpackConfig.optimization
      .minimizer('terser')
        .use(TerserPlugin, [terserOptions(options)])
  })
}


code:
const fs = require('fs')
const path = require('path')
const { chalk, semver, loadModule } = require('@vue/cli-shared-utils')
const isAbsoluteUrl = require('../util/isAbsoluteUrl')

const findExisting = (context, files) => {
  for (const file of files) {
    if (fs.existsSync(path.join(context, file))) {
      return file
    }
  }
}

module.exports = (api, rootOptions) => {
  api.chainWebpack(webpackConfig => {
    const getAssetPath = require('../util/getAssetPath')
    const shadowMode = !!process.env.VUE_CLI_CSS_SHADOW_MODE
    const isProd = process.env.NODE_ENV === 'production'

    const {
      extract = isProd,
      sourceMap = false,
      loaderOptions = {}
    } = rootOptions.css || {}

    const shouldExtract = extract !== false && !shadowMode
    const filename = getAssetPath(
      rootOptions,
      `css/[name]${rootOptions.filenameHashing ? '.[contenthash:8]' : ''}.css`
    )
    const extractOptions = Object.assign({
      filename,
      chunkFilename: filename
    }, extract && typeof extract === 'object' ? extract : {})

    // when project publicPath is a relative path
    // use relative publicPath in extracted CSS based on extract location
    const cssPublicPath = (isAbsoluteUrl(rootOptions.publicPath) || rootOptions.publicPath.startsWith('/'))
      ? rootOptions.publicPath
      : process.env.VUE_CLI_BUILD_TARGET === 'lib'
        // in lib mode, CSS is extracted to dist root.
        ? './'
        : '../'.repeat(
          extractOptions.filename
            .replace(/^\.[/\\]/, '')
            .split(/[/\\]/g)
            .length - 1
        )

    // check if the project has a valid postcss config
    // if it doesn't, don't use postcss-loader for direct style imports
    // because otherwise it would throw error when attempting to load postcss config
    const hasPostCSSConfig = !!(loaderOptions.postcss || api.service.pkg.postcss || findExisting(api.resolve('.'), [
      '.postcssrc',
      '.postcssrc.js',
      'postcss.config.js',
      '.postcssrc.yaml',
      '.postcssrc.json'
    ]))

    if (!hasPostCSSConfig) {
      // #6342
      // NPM 6 may incorrectly hoist postcss 7 to the same level of autoprefixer
      // So we have to run a preflight check to tell the users how to fix it
      const autoprefixerDirectory = path.dirname(require.resolve('autoprefixer/package.json'))
      const postcssPkg = loadModule('postcss/package.json', autoprefixerDirectory)
      const postcssVersion = postcssPkg.version
      if (!semver.satisfies(postcssVersion, '8.x')) {
        throw new Error(
          `The package manager has hoisted a wrong version of ${chalk.cyan('postcss')}, ` +
          `please run ${chalk.cyan('npm i postcss@8 -D')} to fix it.`
        )
      }

      loaderOptions.postcss = {
        postcssOptions: {
          plugins: [
            require('autoprefixer')
          ]
        }
      }
    }

    // if building for production but not extracting CSS, we need to minimize
    // the embbeded inline CSS as they will not be going through the optimizing
    // plugin.
    const needInlineMinification = isProd && !shouldExtract

    const cssnanoOptions = {
      preset: ['default', {
        mergeLonghand: false,
        cssDeclarationSorter: false
      }]
    }
    if (rootOptions.productionSourceMap && sourceMap) {
      cssnanoOptions.map = { inline: false }
    }

    function createCSSRule (lang, test, loader, options) {
      const baseRule = webpackConfig.module.rule(lang).test(test)

      // rules for <style module>
      const vueModulesRule = baseRule.oneOf('vue-modules').resourceQuery(/module/)
      applyLoaders(vueModulesRule, true)

      // rules for <style>
      const vueNormalRule = baseRule.oneOf('vue').resourceQuery(/\?vue/)
      applyLoaders(vueNormalRule)

      // rules for *.module.* files
      const extModulesRule = baseRule.oneOf('normal-modules').test(/\.module\.\w+$/)
      applyLoaders(extModulesRule)

      // rules for normal CSS imports
      const normalRule = baseRule.oneOf('normal')
      applyLoaders(normalRule)

      function applyLoaders (rule, forceCssModule = false) {
        if (shouldExtract) {
          rule
            .use('extract-css-loader')
            .loader(require('mini-css-extract-plugin').loader)
            .options({
              publicPath: cssPublicPath
            })
        } else {
          rule
            .use('vue-style-loader')
            .loader(require.resolve('vue-style-loader'))
            .options({
              sourceMap,
              shadowMode
            })
        }

        const cssLoaderOptions = Object.assign({
          sourceMap,
          importLoaders: (
            1 + // stylePostLoader injected by vue-loader
            1 + // postcss-loader
            (needInlineMinification ? 1 : 0)
          )
        }, loaderOptions.css)

        if (forceCssModule) {
          cssLoaderOptions.modules = {
            ...cssLoaderOptions.modules,
            auto: () => true
          }
        }

        if (cssLoaderOptions.modules) {
          cssLoaderOptions.modules = {
            localIdentName: '[name]_[local]_[hash:base64:5]',
            ...cssLoaderOptions.modules
          }
        }

        rule
          .use('css-loader')
          .loader(require.resolve('css-loader'))
          .options(cssLoaderOptions)

        if (needInlineMinification) {
          rule
            .use('cssnano')
            .loader(require.resolve('postcss-loader'))
            .options({
              sourceMap,
              postcssOptions: {
                plugins: [require('cssnano')(cssnanoOptions)]
              }
            })
        }

        rule
          .use('postcss-loader')
          .loader(require.resolve('postcss-loader'))
          .options(Object.assign({ sourceMap }, loaderOptions.postcss))

        if (loader) {
          let resolvedLoader
          try {
            resolvedLoader = require.resolve(loader)
          } catch (error) {
            resolvedLoader = loader
          }

          rule
            .use(loader)
            .loader(resolvedLoader)
            .options(Object.assign({ sourceMap }, options))
        }
      }
    }

    createCSSRule('css', /\.css$/)
    createCSSRule('postcss', /\.p(ost)?css$/)
    createCSSRule('scss', /\.scss$/, 'sass-loader', Object.assign(
      {},
      loaderOptions.scss || loaderOptions.sass
    ))
    createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign(
      {},
      loaderOptions.sass,
      {
        sassOptions: Object.assign(
          {},
          loaderOptions.sass && loaderOptions.sass.sassOptions,
          {
            indentedSyntax: true
          }
        )
      }
    ))
    createCSSRule('less', /\.less$/, 'less-loader', loaderOptions.less)
    createCSSRule('stylus', /\.styl(us)?$/, 'stylus-loader', loaderOptions.stylus)

    // inject CSS extraction plugin
    if (shouldExtract) {
      webpackConfig
        .plugin('extract-css')
          .use(require('mini-css-extract-plugin'), [extractOptions])

      // minify extracted CSS
      webpackConfig.optimization
        .minimizer('css')
          .use(require('css-minimizer-webpack-plugin'), [{
            parallel: rootOptions.parallel,
            minimizerOptions: cssnanoOptions
          }])
    }
  })
}


code:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Vue App</title>


code:
/** @type {import('@vue/cli-service').ServicePlugin} */
module.exports = (api, options) => {
  api.chainWebpack(webpackConfig => {
    if (process.env.NODE_ENV === 'production') {
      webpackConfig
        .mode('production')
        .devtool(options.productionSourceMap ? 'source-map' : false)

      // disable optimization during tests to speed things up
      if (process.env.VUE_CLI_TEST && !process.env.VUE_CLI_TEST_MINIMIZE) {
        webpackConfig.optimization.minimize(false)
      }
    }
  })
}


code:
// @ts-check
const TerserPlugin = require('terser-webpack-plugin')

const genTerserOptions = (defaultOptions, options) => {
  const userOptions = options.terser && options.terser.terserOptions
  // user's config is first
  return {
    ...defaultOptions,
    ...userOptions
  }
}

const terserMinify = (options) => ({
  terserOptions: genTerserOptions(
    {
      compress: {
        // turn off flags with small gains to speed up minification
        arrows: false,
        collapse_vars: false, // 0.3kb
        comparisons: false,
        computed_props: false,
        hoist_funs: false,
        hoist_props: false,
        hoist_vars: false,
        inline: false,
        loops: false,
        negate_iife: false,
        properties: false,
        reduce_funcs: false,
        reduce_vars: false,
        switches: false,
        toplevel: false,
        typeofs: false,

        // a few flags with noticeable gains/speed ratio
        // numbers based on out of the box vendor bundle
        booleans: true, // 0.7kb
        if_return: true, // 0.4kb
        sequences: true, // 0.7kb
        unused: true, // 2.3kb

        // required features to drop conditional branches
        conditionals: true,
        dead_code: true,
        evaluate: true
      },
      mangle: {
        safari10: true
      }
    },
    options
  ),
  parallel: options.parallel,
  extractComments: false
})

// `terserOptions` options will be passed to `esbuild`
// Link to options - https://esbuild.github.io/api/#minify
const esbuildMinify = (options) => ({
  minify: TerserPlugin.esbuildMinify,
  terserOptions: genTerserOptions(
    {
      minify: false,
      minifyWhitespace: true,
      minifyIdentifiers: false,
      minifySyntax: true
    },
    options
  ),
  parallel: options.parallel
})

// `terserOptions` options will be passed to `swc` (`@swc/core`)
// Link to options - https://swc.rs/docs/config-js-minify
const swcMinify = (options) => ({
  minify: TerserPlugin.swcMinify,
  terserOptions: genTerserOptions(
    {
      compress: {
        unused: true
      },
      mangle: true
    },
    options
  ),
  parallel: options.parallel
})

// `terserOptions` options will be passed to `uglify-js`
// Link to options - https://github.com/mishoo/UglifyJS#minify-options
const uglifyJsMinify = (options) => ({
  minify: TerserPlugin.uglifyJsMinify,
  terserOptions: genTerserOptions({}, options),
  parallel: options.parallel
})

// Currently we do not allow custom minify function
const getMinify = (options) => {
  const { minify = 'terser' } = options.terser || {}

  const minifyMap = {
    terser: terserMinify,
    esbuild: esbuildMinify,
    swc: swcMinify,
    uglifyJs: uglifyJsMinify
  }
  return minifyMap[minify](options)
}

module.exports = getMinify


code:
const { createSchema, validate } = require('@vue/cli-shared-utils')

const schema = createSchema(joi => joi.object({
  publicPath: joi.string().allow(''),
  outputDir: joi.string(),
  assetsDir: joi.string().allow(''),
  indexPath: joi.string(),
  filenameHashing: joi.boolean(),
  runtimeCompiler: joi.boolean(),
  transpileDependencies: joi.alternatives().try(
    joi.boolean(),
    joi.array()
  ),
  productionSourceMap: joi.boolean(),
  parallel: joi.alternatives().try(
    joi.boolean(),
    joi.number().integer()
  ),
  devServer: joi.object(),
  pages: joi.object().pattern(
    /\w+/,
    joi.alternatives().try(
      joi.string().required(),
      joi.array().items(joi.string().required()),

      joi.object().keys({
        entry: joi.alternatives().try(
          joi.string().required(),
          joi.array().items(joi.string().required())
        ).required()
      }).unknown(true)
    )
  ),
  crossorigin: joi.string().valid('', 'anonymous', 'use-credentials'),
  integrity: joi.boolean(),

  // css
  css: joi.object({
    extract: joi.alternatives().try(joi.boolean(), joi.object()),
    sourceMap: joi.boolean(),
    loaderOptions: joi.object({
      css: joi.object(),
      sass: joi.object(),
      scss: joi.object(),
      less: joi.object(),
      stylus: joi.object(),
      postcss: joi.object()
    })
  }),

  // webpack
  chainWebpack: joi.func(),
  configureWebpack: joi.alternatives().try(
    joi.object(),
    joi.func()
  ),

  // known runtime options for built-in plugins
  lintOnSave: joi.any().valid(true, false, 'error', 'warning', 'default'),
  pwa: joi.object(),

  // terser
  terser: joi.object({
    minify: joi.string().valid('terser', 'esbuild', 'swc', 'uglifyJs'),
    terserOptions: joi.object()
  }),

  // 3rd party plugin options
  pluginOptions: joi.object()
}))

exports.validate = (options, cb) => {
  validate(options, schema, cb)
}

// #2110
// https://github.com/nodejs/node/issues/19022
// in some cases cpus() returns undefined, and may simply throw in the future
function hasMultipleCores () {
  try {
    return require('os').cpus().length > 1
  } catch (e) {
    return false
  }
}

exports.defaults = () => ({
  // project deployment base
  publicPath: '/',

  // where to output built files
  outputDir: 'dist',

  // where to put static assets (js/css/img/font/...)
  assetsDir: '',

  // filename for index.html (relative to outputDir)
  indexPath: 'index.html',

  // whether filename will contain hash part
  filenameHashing: true,

  // boolean, use full build?
  runtimeCompiler: false,

  // whether to transpile all dependencies
  transpileDependencies: false,

  // sourceMap for production build?
  productionSourceMap: !process.env.VUE_CLI_TEST,

  // use thread-loader for babel & TS in production build
  // enabled by default if the machine has more than 1 cores
  parallel: hasMultipleCores(),

  // multi-page config
  pages: undefined,

  // <script type="module" crossorigin="use-credentials">
  // #1656, #1867, #2025
  crossorigin: undefined,

  // subresource integrity
  integrity: false,

  css: {
    // extract: true,
    // modules: false,
    // sourceMap: false,
    // loaderOptions: {}
  },

  // whether to use eslint-loader
  lintOnSave: 'default',

  devServer: {
    /*
    open: process.platform === 'darwin',
    host: '0.0.0.0',
    port: 8080,
    https: false,
    hotOnly: false,
    proxy: null, // string | Object
    before: app => {}
  */
  }
})


code:
const path = require('path')

module.exports = function getAssetPath (options, filePath) {
  return options.assetsDir
    ? path.posix.join(options.assetsDir, filePath)
    : filePath
}


code:
module.exports = function getBaseUrl (options) {
  return options.publicPath === 'auto' ? '' : options.publicPath
}


code:
module.exports = function getPadLength (obj) {
  let longest = 10
  for (const name in obj) {
    if (name.length + 1 > longest) {
      longest = name.length + 1
    }
  }
  return longest
}


code:
const { semver, loadModule } = require('@vue/cli-shared-utils')

/**
 * Get the major Vue version that the user project uses
 * @param {string} cwd the user project root
 * @returns {2|3}
 */
module.exports = function getVueMajor (cwd) {
  const vue = loadModule('vue', cwd)
  // TODO: make Vue 3 the default version
  const vueMajor = vue ? semver.major(vue.version) : 2
  return vueMajor
}


code:
module.exports = function isAbsoluteUrl (url) {
  // A URL is considered absolute if it begins with "<scheme>://" or "//"
  return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
}


code:
const fs = require('fs')
const path = require('path')
const { pathToFileURL } = require('url')
const isFileEsm = require('is-file-esm')
const { loadModule } = require('@vue/cli-shared-utils')

module.exports = function loadFileConfig (context) {
  let fileConfig, fileConfigPath

  const possibleConfigPaths = [
    process.env.VUE_CLI_SERVICE_CONFIG_PATH,
    './vue.config.js',
    './vue.config.cjs',
    './vue.config.mjs'
  ]
  for (const p of possibleConfigPaths) {
    const resolvedPath = p && path.resolve(context, p)
    if (resolvedPath && fs.existsSync(resolvedPath)) {
      fileConfigPath = resolvedPath
      break
    }
  }

  if (fileConfigPath) {
    const { esm } = isFileEsm.sync(fileConfigPath)

    if (esm) {
      fileConfig = import(pathToFileURL(fileConfigPath))
    } else {
      fileConfig = loadModule(fileConfigPath, context)
    }
  }

  return {
    fileConfig,
    fileConfigPath
  }
}


code:
/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file at
 * https://github.com/facebookincubator/create-react-app/blob/master/LICENSE
 */

const fs = require('fs')
const url = require('url')
const path = require('path')
const { chalk } = require('@vue/cli-shared-utils')
const address = require('address')

const defaultConfig = {
  logLevel: 'silent',
  secure: false,
  changeOrigin: true,
  ws: true,
  xfwd: true
}

module.exports = function prepareProxy (proxy, appPublicFolder) {
  // `proxy` lets you specify alternate servers for specific requests.
  // It can either be a string or an object conforming to the Webpack dev server proxy configuration
  // https://webpack.github.io/docs/webpack-dev-server.html
  if (!proxy) {
    return undefined
  }
  if (Array.isArray(proxy) || (typeof proxy !== 'object' && typeof proxy !== 'string')) {
    console.log(
      chalk.red(
        'When specified, "proxy" in package.json must be a string or an object.'
      )
    )
    console.log(
      chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".')
    )
    console.log(
      chalk.red(
        'Either remove "proxy" from package.json, or make it an object.'
      )
    )
    process.exit(1)
  }

  // If proxy is specified, let it handle any request except for
  // files in the public folder and requests to the WebpackDevServer socket endpoint.
  // https://github.com/facebook/create-react-app/issues/6720
  function mayProxy (pathname) {
    const maybePublicPath = path.resolve(appPublicFolder, pathname.slice(1))
    const isPublicFileRequest = fs.existsSync(maybePublicPath) && fs.statSync(maybePublicPath).isFile()
    const isWdsEndpointRequest = pathname.startsWith('/sockjs-node') // used by webpackHotDevClient
    return !(isPublicFileRequest || isWdsEndpointRequest)
  }

  function createProxyEntry (target, usersOnProxyReq, context) {
    // #2478
    // There're a little-known use case that the `target` field is an object rather than a string
    // https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/https.md
    if (typeof target === 'string' && process.platform === 'win32') {
      target = resolveLoopback(target)
    }
    return {
      target,
      context (pathname, req) {
        // is a static asset
        if (!mayProxy(pathname)) {
          return false
        }
        if (context) {
          // Explicit context, e.g. /api
          return pathname.match(context)
        } else {
          // not a static request
          if (req.method !== 'GET') {
            return true
          }
          // Heuristics: if request `accept`s text/html, we pick /index.html.
          // Modern browsers include text/html into `accept` header when navigating.
          // However API calls like `fetch()` won’t generally accept text/html.
          // If this heuristic doesn’t work well for you, use a custom `proxy` object.
          return (
            req.headers.accept &&
            req.headers.accept.indexOf('text/html') === -1
          )
        }
      },
      onProxyReq (proxyReq, req, res) {
        if (usersOnProxyReq) {
          usersOnProxyReq(proxyReq, req, res)
        }
        // Browsers may send Origin headers even with same-origin
        // requests. To prevent CORS issues, we have to change
        // the Origin to match the target URL.
        if (!proxyReq.agent && proxyReq.getHeader('origin')) {
          proxyReq.setHeader('origin', target)
        }
      },
      onError: onProxyError(target)
    }
  }

  // Support proxy as a string for those who are using the simple proxy option
  if (typeof proxy === 'string') {
    if (!/^http(s)?:\/\//.test(proxy)) {
      console.log(
        chalk.red(
          'When "proxy" is specified in package.json it must start with either http:// or https://'
        )
      )
      process.exit(1)
    }

    return [
      Object.assign({}, defaultConfig, createProxyEntry(proxy))
    ]
  }

  // Otherwise, proxy is an object so create an array of proxies to pass to webpackDevServer
  return Object.keys(proxy).map(context => {
    const config = proxy[context]
    if (!Object.prototype.hasOwnProperty.call(config, 'target')) {
      console.log(
        chalk.red(
          'When `proxy` in package.json is an object, each `context` object must have a ' +
            '`target` property specified as a url string'
        )
      )
      process.exit(1)
    }
    const entry = createProxyEntry(config.target, config.onProxyReq, context)
    return Object.assign({}, defaultConfig, config, entry)
  })
}

function resolveLoopback (proxy) {
  const o = new url.URL(proxy)
  o.host = undefined
  if (o.hostname !== 'localhost') {
    return proxy
  }
  // Unfortunately, many languages (unlike node) do not yet support IPv6.
  // This means even though localhost resolves to ::1, the application
  // must fall back to IPv4 (on 127.0.0.1).
  // We can re-enable this in a few years.
  /* try {
    o.hostname = address.ipv6() ? '::1' : '127.0.0.1';
  } catch (_ignored) {
    o.hostname = '127.0.0.1';
  } */

  try {
    // Check if we're on a network; if we are, chances are we can resolve
    // localhost. Otherwise, we can just be safe and assume localhost is
    // IPv4 for maximum compatibility.
    if (!address.ip()) {
      o.hostname = '127.0.0.1'
    }
  } catch (_ignored) {
    o.hostname = '127.0.0.1'
  }
  return url.format(o)
}

// We need to provide a custom onError function for httpProxyMiddleware.
// It allows us to log custom error messages on the console.
function onProxyError (proxy) {
  return (err, req, res) => {
    const host = req.headers && req.headers.host
    console.log(
      chalk.red('Proxy error:') +
        ' Could not proxy request ' +
        chalk.cyan(req.url) +
        ' from ' +
        chalk.cyan(host) +
        ' to ' +
        chalk.cyan(proxy) +
        '.'
    )
    console.log(
      'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' +
        chalk.cyan(err.code) +
        ').'
    )
    console.log()

    // And immediately send the proper error response to the client.
    // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
    if (res.writeHead && !res.headersSent) {
      res.writeHead(500)
    }
    res.end(
      'Proxy error: Could not proxy request ' +
        req.url +
        ' from ' +
        host +
        ' to ' +
        proxy +
        ' (' +
        err.code +
        ').'
    )
  }
}


code:
/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file at
 * https://github.com/facebookincubator/create-react-app/blob/master/LICENSE
 */

const url = require('url')
const { chalk } = require('@vue/cli-shared-utils')
const address = require('address')
const defaultGateway = require('default-gateway')

module.exports = function prepareUrls (protocol, host, port, pathname = '/') {
  const formatUrl = hostname =>
    url.format({
      protocol,
      hostname,
      port,
      pathname
    })
  const prettyPrintUrl = hostname =>
    url.format({
      protocol,
      hostname,
      port: chalk.bold(port),
      pathname
    })

  const isUnspecifiedHost = host === '0.0.0.0' || host === '::'
  let prettyHost, lanUrlForConfig
  let lanUrlForTerminal = chalk.gray('unavailable')
  if (isUnspecifiedHost) {
    prettyHost = 'localhost'
    try {
      // This can only return an IPv4 address
      const result = defaultGateway.v4.sync()
      lanUrlForConfig = address.ip(result && result.interface)
      if (lanUrlForConfig) {
        // Check if the address is a private ip
        // https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
        if (
          /^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(
            lanUrlForConfig
          )
        ) {
          // Address is private, format it for later use
          lanUrlForTerminal = prettyPrintUrl(lanUrlForConfig)
        } else {
          // Address is not private, so we will discard it
          lanUrlForConfig = undefined
        }
      }
    } catch (_e) {
      // ignored
    }
  } else {
    prettyHost = host
    lanUrlForConfig = host
    lanUrlForTerminal = prettyPrintUrl(lanUrlForConfig)
  }
  const localUrlForTerminal = prettyPrintUrl(prettyHost)
  const localUrlForBrowser = formatUrl(prettyHost)
  return {
    lanUrlForConfig,
    lanUrlForTerminal,
    localUrlForTerminal,
    localUrlForBrowser
  }
}


code:
const getBaseUrl = require('./getBaseUrl')
const prefixRE = /^VUE_APP_/

module.exports = function resolveClientEnv (options, raw) {
  const env = {}
  Object.keys(process.env).forEach(key => {
    if (prefixRE.test(key) || key === 'NODE_ENV') {
      env[key] = process.env[key]
    }
  })
  env.BASE_URL = getBaseUrl(options)

  if (raw) {
    return env
  }

  for (const key in env) {
    env[key] = JSON.stringify(env[key])
  }
  return {
    'process.env': env
  }
}


code:
const { chalk } = require('@vue/cli-shared-utils')

const rules = [
  {
    type: 'cant-resolve-loader',
    re: /Can't resolve '(.*loader)'/,
    msg: (e, match) => (
      `Failed to resolve loader: ${chalk.yellow(match[1])}\n` +
      `You may need to install it.`
    )
  }
]

exports.transformer = error => {
  if (error.webpackError) {
    const message = typeof error.webpackError === 'string'
      ? error.webpackError
      : error.webpackError.message || ''
    for (const { re, msg, type } of rules) {
      const match = message.match(re)
      if (match) {
        return Object.assign({}, error, {
          // type is necessary to avoid being printed as default error
          // by friendly-error-webpack-plugin
          type,
          shortMessage: msg(error, match)
        })
      }
    }
    // no match, unknown webpack error without a message.
    // friendly-error-webpack-plugin fails to handle this.
    if (!error.message) {
      return Object.assign({}, error, {
        type: 'unknown-webpack-error',
        shortMessage: message
      })
    }
  }
  return error
}

exports.formatter = errors => {
  errors = errors.filter(e => e.shortMessage)
  if (errors.length) {
    return errors.map(e => e.shortMessage)
  }
}


code:
const path = require('path')

module.exports = function resolveLocal (...args) {
  return path.join(__dirname, '../../', ...args)
}


code:
const path = require('path')
const { chalk, warn, error } = require('@vue/cli-shared-utils')
const { validate } = require('../options')

function ensureSlash (config, key) {
  const val = config[key]
  if (typeof val === 'string') {
    config[key] = val.replace(/([^/])$/, '$1/')
  }
}

function removeSlash (config, key) {
  if (typeof config[key] === 'string') {
    config[key] = config[key].replace(/\/$/g, '')
  }
}

module.exports = function resolveUserConfig ({
  inlineOptions,
  pkgConfig,
  fileConfig,
  fileConfigPath
}) {
  if (fileConfig) {
    if (typeof fileConfig === 'function') {
      fileConfig = fileConfig()
    }

    if (!fileConfig || typeof fileConfig !== 'object') {
      throw new Error(
        `Error loading ${chalk.bold(fileConfigPath)}: ` +
        `should export an object or a function that returns object.`
      )
    }
  }

  // package.vue
  if (pkgConfig && typeof pkgConfig !== 'object') {
    throw new Error(
      `Error loading Vue CLI config in ${chalk.bold(`package.json`)}: ` +
      `the "vue" field should be an object.`
    )
  }

  let resolved, resolvedFrom
  if (fileConfig) {
    const configFileName = path.basename(fileConfigPath)
    if (pkgConfig) {
      warn(
        `"vue" field in package.json ignored ` +
        `due to presence of ${chalk.bold(configFileName)}.`
      )
      warn(
        `You should migrate it into ${chalk.bold(configFileName)} ` +
        `and remove it from package.json.`
      )
    }
    resolved = fileConfig
    resolvedFrom = configFileName
  } else if (pkgConfig) {
    resolved = pkgConfig
    resolvedFrom = '"vue" field in package.json'
  } else {
    resolved = inlineOptions || {}
    resolvedFrom = 'inline options'
  }

  // normalize some options
  if (resolved.publicPath !== 'auto') {
    ensureSlash(resolved, 'publicPath')
  }
  if (typeof resolved.publicPath === 'string') {
    resolved.publicPath = resolved.publicPath.replace(/^\.\//, '')
  }
  removeSlash(resolved, 'outputDir')

  // validate options
  validate(resolved, msg => {
    error(`Invalid options in ${chalk.bold(resolvedFrom)}: ${msg}`)
  })

  return resolved
}


code:
// copied from @vue/babel-preset-app

const { semver } = require('@vue/cli-shared-utils')
const { default: getTargets } = require('@babel/helper-compilation-targets')

// See the result at <https://github.com/babel/babel/blob/v7.13.15/packages/babel-compat-data/data/native-modules.json>
const allModuleTargets = getTargets(
  { esmodules: true },
  { ignoreBrowserslistConfig: true }
)

function getIntersectionTargets (targets, constraintTargets) {
  const intersection = Object.keys(constraintTargets).reduce(
    (results, browser) => {
      // exclude the browsers that the user does not need
      if (!targets[browser]) {
        return results
      }

      // if the user-specified version is higher the minimum version that supports esmodule, than use it
      results[browser] = semver.gt(
        semver.coerce(constraintTargets[browser]),
        semver.coerce(targets[browser])
      )
        ? constraintTargets[browser]
        : targets[browser]

      return results
    },
    {}
  )

  return intersection
}

function getModuleTargets (targets) {
  // use the intersection of modern mode browsers and user defined targets config
  return getIntersectionTargets(targets, allModuleTargets)
}

function doAllTargetsSupportModule (targets) {
  const browserList = Object.keys(targets)

  return browserList.every(browserName => {
    if (!allModuleTargets[browserName]) {
      return false
    }

    return semver.gte(
      semver.coerce(targets[browserName]),
      semver.coerce(allModuleTargets[browserName])
    )
  })
}

// get browserslist targets in current working directory
const projectTargets = getTargets()
const projectModuleTargets = getModuleTargets(projectTargets)
const allProjectTargetsSupportModule = doAllTargetsSupportModule(projectTargets)

module.exports = {
  getTargets,
  getModuleTargets,
  getIntersectionTargets,
  doAllTargetsSupportModule,

  projectTargets,
  projectModuleTargets,
  allProjectTargetsSupportModule
}


code:
module.exports = function validateWebpackConfig (
  webpackConfig,
  api,
  options,
  target = 'app'
) {
  const singleConfig = Array.isArray(webpackConfig)
    ? webpackConfig[0]
    : webpackConfig

  const actualTargetDir = singleConfig.output.path

  if (actualTargetDir !== api.resolve(options.outputDir)) {
    // user directly modifies output.path in configureWebpack or chainWebpack.
    // this is not supported because there's no way for us to give copy
    // plugin the correct value this way.
    throw new Error(
      `\n\nConfiguration Error: ` +
      `Avoid modifying webpack output.path directly. ` +
      `Use the "outputDir" option instead.\n`
    )
  }

  if (actualTargetDir === api.service.context) {
    throw new Error(
      `\n\nConfiguration Error: ` +
      `Do not set output directory to project root.\n`
    )
  }

  if (target === 'app' && singleConfig.output.publicPath !== options.publicPath) {
    throw new Error(
      `\n\nConfiguration Error: ` +
      `Avoid modifying webpack output.publicPath directly. ` +
      `Use the "publicPath" option instead.\n`
    )
  }
}


code:
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = class CorsPlugin {
  constructor ({ publicPath, crossorigin, integrity }) {
    this.crossorigin = crossorigin
    this.integrity = integrity
    this.publicPath = publicPath
  }

  apply (compiler) {
    const ID = `vue-cli-cors-plugin`
    compiler.hooks.compilation.tap(ID, compilation => {
      const ssri = require('ssri')

      const computeHash = url => {
        const filename = url.replace(this.publicPath, '')
        const asset = compilation.assets[filename]
        if (asset) {
          const src = asset.source()
          const integrity = ssri.fromData(src, {
            algorithms: ['sha384']
          })
          return integrity.toString()
        }
      }

      HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tap(ID, data => {
        const tags = [...data.headTags, ...data.bodyTags]
        if (this.crossorigin != null) {
          tags.forEach(tag => {
            if (tag.tagName === 'script' || tag.tagName === 'link') {
              tag.attributes.crossorigin = this.crossorigin
            }
          })
        }
        if (this.integrity) {
          tags.forEach(tag => {
            if (tag.tagName === 'script') {
              const hash = computeHash(tag.attributes.src)
              if (hash) {
                tag.attributes.integrity = hash
              }
            } else if (tag.tagName === 'link' && tag.attributes.rel === 'stylesheet') {
              const hash = computeHash(tag.attributes.href)
              if (hash) {
                tag.attributes.integrity = hash
              }
            }
          })

          // when using SRI, Chrome somehow cannot reuse
          // the preloaded resource, and causes the files to be downloaded twice.
          // this is a Chrome bug (https://bugs.chromium.org/p/chromium/issues/detail?id=677022)
          // for now we disable preload if SRI is used.
          data.headTags = data.headTags.filter(tag => {
            return !(
              tag.tagName === 'link' &&
              tag.attributes.rel === 'preload'
            )
          })
        }
      })

      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tap(ID, data => {
        data.html = data.html.replace(/\scrossorigin=""/g, ' crossorigin')
      })
    })
  }
}


code:
// From https://github.com/FormidableLabs/webpack-dashboard/blob/7f99b31c5f00a7818d8129cb8a8fc6eb1b71799c/plugin/index.js
// Modified by Guillaume Chau (Akryum)

/* eslint-disable max-params, max-statements */
'use strict'

const path = require('path')
const fs = require('fs-extra')
const webpack = require('webpack')
const { IpcMessenger } = require('@vue/cli-shared-utils')
const { analyzeBundle } = require('./analyzeBundle')

const ID = 'vue-cli-dashboard-plugin'
const ONE_SECOND = 1000
const FILENAME_QUERY_REGEXP = /\?.*$/

const ipc = new IpcMessenger()

function getTimeMessage (timer) {
  let time = Date.now() - timer

  if (time >= ONE_SECOND) {
    time /= ONE_SECOND
    time = Math.round(time)
    time += 's'
  } else {
    time += 'ms'
  }

  return ` (${time})`
}

class DashboardPlugin {
  constructor (options) {
    this.type = options.type
    if (this.type === 'build' && options.moduleBuild) {
      this.type = 'build-modern'
    }
    this.watching = false
    this.autoDisconnect = !options.keepAlive
  }

  cleanup () {
    this.sendData = null
    if (this.autoDisconnect) ipc.disconnect()
  }

  apply (compiler) {
    let sendData = this.sendData
    let timer
    let inProgress = false

    let assetSources = new Map()

    if (!sendData) {
      sendData = data => ipc.send({
        webpackDashboardData: {
          type: this.type,
          value: data
        }
      })
    }

    // Progress status
    let progressTime = Date.now()
    const progressPlugin = new webpack.ProgressPlugin((percent, msg) => {
      // in webpack 5, progress plugin will continue sending progresses even after the done hook
      // for things like caching, causing the progress indicator stuck at 0.99
      // so we have to use a flag to stop sending such `compiling` progress data
      if (!inProgress) {
        return
      }

      // Debouncing
      const time = Date.now()
      if (time - progressTime > 300) {
        progressTime = time
        sendData([
          {
            type: 'status',
            value: 'Compiling'
          },
          {
            type: 'progress',
            value: percent
          },
          {
            type: 'operations',
            value: msg + getTimeMessage(timer)
          }
        ])
      }
    })
    progressPlugin.apply(compiler)

    compiler.hooks.watchRun.tap(ID, c => {
      this.watching = true
    })

    compiler.hooks.run.tap(ID, c => {
      this.watching = false
    })

    compiler.hooks.compile.tap(ID, () => {
      inProgress = true
      timer = Date.now()

      sendData([
        {
          type: 'status',
          value: 'Compiling'
        },
        {
          type: 'progress',
          value: 0
        }
      ])
    })

    compiler.hooks.invalid.tap(ID, () => {
      sendData([
        {
          type: 'status',
          value: 'Invalidated'
        },
        {
          type: 'progress',
          value: 0
        },
        {
          type: 'operations',
          value: 'idle'
        }
      ])
    })

    compiler.hooks.failed.tap(ID, () => {
      sendData([
        {
          type: 'status',
          value: 'Failed'
        },
        {
          type: 'operations',
          value: `idle${getTimeMessage(timer)}`
        }
      ])
      inProgress = false
    })

    compiler.hooks.afterEmit.tap(ID, compilation => {
      assetSources = new Map()
      for (const name in compilation.assets) {
        const asset = compilation.assets[name]
        const filename = name.replace(FILENAME_QUERY_REGEXP, '')
        try {
          assetSources.set(filename, asset.source())
        } catch (e) {
          const webpackFs = compiler.outputFileSystem
          const fullPath = (webpackFs.join || path.join)(compiler.options.output.path, filename)
          const buf = webpackFs.readFileSync(fullPath)
          assetSources.set(filename, buf.toString())
        }
      }
    })

    compiler.hooks.done.tap(ID, stats => {
      let statsData = stats.toJson()
      // Sometimes all the information is located in `children` array
      if ((!statsData.assets || !statsData.assets.length) && statsData.children && statsData.children.length) {
        statsData = statsData.children[0]
      }

      const outputPath = compiler.options.output.path
      statsData.assets.forEach(asset => {
        // Removing query part from filename (yes, somebody uses it for some reason and Webpack supports it)
        asset.name = asset.name.replace(FILENAME_QUERY_REGEXP, '')
        asset.fullPath = path.join(outputPath, asset.name)
      })
      // Analyze the assets and update sizes on assets and modules
      analyzeBundle(statsData, assetSources)

      const hasErrors = stats.hasErrors()

      sendData([
        {
          type: 'status',
          value: hasErrors ? 'Failed' : 'Success'
        },
        {
          type: 'progress',
          value: 1
        },
        {
          type: 'operations',
          value: `idle${getTimeMessage(timer)}`
        }
      ])
      inProgress = false

      const statsFile = path.resolve(process.cwd(), `./node_modules/.stats-${this.type}.json`)
      fs.writeJson(statsFile, {
        errors: hasErrors,
        warnings: stats.hasWarnings(),
        data: statsData
      }).then(() => {
        sendData([
          {
            type: 'stats'
          }
        ])

        if (!this.watching) {
          this.cleanup()
        }
      }).catch(error => {
        console.error(error)
      })
    })
  }
}

module.exports = DashboardPlugin


code:
const fs = require('fs-extra')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
class ModernModePlugin {
  constructor ({ targetDir, isModuleBuild }) {
    this.targetDir = targetDir
    this.isModuleBuild = isModuleBuild
  }

  apply (compiler) {
    if (!this.isModuleBuild) {
      this.applyLegacy(compiler)
    } else {
      this.applyModule(compiler)
    }
  }

  applyLegacy (compiler) {
    const ID = `vue-cli-legacy-bundle`
    compiler.hooks.compilation.tap(ID, compilation => {
      HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(ID, async (data, cb) => {
        // get stats, write to disk
        await fs.ensureDir(this.targetDir)
        const htmlName = path.basename(data.plugin.options.filename)
        // Watch out for output files in sub directories
        const htmlPath = path.dirname(data.plugin.options.filename)
        const tempFilename = path.join(this.targetDir, htmlPath, `legacy-assets-${htmlName}.json`)
        await fs.mkdirp(path.dirname(tempFilename))

        let tags = data.bodyTags
        if (data.plugin.options.scriptLoading === 'defer') {
          tags = data.headTags
        }
        await fs.writeFile(tempFilename, JSON.stringify(tags))
        cb()
      })
    })
  }

  applyModule (compiler) {
    const ID = `vue-cli-modern-bundle`
    compiler.hooks.compilation.tap(ID, compilation => {
      HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(ID, async (data, cb) => {
        let tags = data.bodyTags
        if (data.plugin.options.scriptLoading === 'defer') {
          tags = data.headTags
        }
        // use <script type="module"> for modern assets
        tags.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 htmlName = path.basename(data.plugin.options.filename)
        // Watch out for output files in sub directories
        const htmlPath = path.dirname(data.plugin.options.filename)
        const tempFilename = path.join(this.targetDir, htmlPath, `legacy-assets-${htmlName}.json`)
        const legacyAssets = JSON.parse(await fs.readFile(tempFilename, 'utf-8'))
          .filter(a => a.tagName === 'script' && a.attributes)
        legacyAssets.forEach(a => { a.attributes.nomodule = '' })

        tags.push(...legacyAssets)
        await fs.remove(tempFilename)
        cb()
      })

      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tap(ID, data => {
        data.html = data.html.replace(/\snomodule="">/g, ' nomodule>')
      })
    })
  }
}

module.exports = ModernModePlugin


code:
const fs = require('fs-extra')

module.exports = class MovePlugin {
  constructor (from, to) {
    this.from = from
    this.to = to
  }

  apply (compiler) {
    compiler.hooks.done.tap('move-plugin', () => {
      if (fs.existsSync(this.from)) {
        fs.moveSync(this.from, this.to, { overwrite: true })
      }
    })
  }
}