228 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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',
 | 
						|
            __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: '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)])
 | 
						|
  })
 | 
						|
}
 |