123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- const { semver, loadModule } = require('@vue/cli-shared-utils')
- module.exports = (api, options) => {
- api.chainWebpack(webpackConfig => {
- const isLegacyBundle = process.env.VUE_CLI_MODERN_MODE && !process.env.VUE_CLI_MODERN_BUILD
- const resolveLocal = require('../util/resolveLocal')
- const getAssetPath = require('../util/getAssetPath')
- const inlineLimit = 4096
- const genAssetSubPath = dir => {
- return getAssetPath(
- options,
- `${dir}/[name]${options.filenameHashing ? '.[hash:8]' : ''}.[ext]`
- )
- }
- const genUrlLoaderOptions = dir => {
- return {
- limit: inlineLimit,
- // use explicit fallback to avoid regression in url-loader>=1.1.0
- fallback: {
- loader: require.resolve('file-loader'),
- options: {
- name: genAssetSubPath(dir)
- }
- }
- }
- }
- 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
- // This plugin can be removed once we switch to Webpack 6
- .plugin('pnp')
- .use({ ...require('pnp-webpack-plugin') })
- .end()
- .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
- .plugin('pnp-loaders')
- .use({ ...require('pnp-webpack-plugin').topLevelLoader })
- .end()
- .modules
- .add('node_modules')
- .add(api.resolve('node_modules'))
- .add(resolveLocal('node_modules'))
- webpackConfig.module
- .noParse(/^(vue|vue-router|vuex|vuex-router-sync)$/)
- webpackConfig.module
- .rule('mjs')
- .test(/\.mjs$/)
- .include
- .add(/node_modules/)
- .end()
- .type('javascript/auto')
- // js is handled by cli-plugin-babel ---------------------------------------
- // vue-loader --------------------------------------------------------------
- // try to load vue in the project
- // fallback to peer vue package in the instant prototyping environment
- const vue = loadModule('vue', api.service.context) || loadModule('vue', __dirname)
- if (vue && semver.major(vue.version) === 2) {
- // for Vue 2 projects
- const partialIdentifier = {
- 'vue-loader': require('vue-loader/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'
- )
- webpackConfig.module
- .rule('vue')
- .test(/\.vue$/)
- .use('cache-loader')
- .loader(require.resolve('cache-loader'))
- .options(vueLoaderCacheConfig)
- .end()
- .use('vue-loader')
- .loader(require.resolve('vue-loader'))
- .options(Object.assign({
- compilerOptions: {
- whitespace: 'condense'
- }
- }, vueLoaderCacheConfig))
- webpackConfig
- .plugin('vue-loader')
- .use(require('vue-loader').VueLoaderPlugin)
- } else if (vue && semver.major(vue.version) === 3) {
- // for Vue 3 projects
- const vueLoaderCacheConfig = api.genCacheConfig('vue-loader', {
- 'vue-loader': require('vue-loader-v16/package.json').version,
- '@vue/compiler-sfc': require('@vue/compiler-sfc/package.json').version
- })
- webpackConfig.resolve
- .alias
- .set(
- 'vue$',
- options.runtimeCompiler
- ? 'vue/dist/vue.esm-bundler.js'
- : 'vue/dist/vue.runtime.esm-bundler.js'
- )
- webpackConfig.module
- .rule('vue')
- .test(/\.vue$/)
- .use('cache-loader')
- .loader(require.resolve('cache-loader'))
- .options(vueLoaderCacheConfig)
- .end()
- .use('vue-loader')
- .loader(require.resolve('vue-loader-v16'))
- .options({
- ...vueLoaderCacheConfig,
- babelParserPlugins: ['jsx', 'classProperties', 'decorators-legacy']
- })
- .end()
- .end()
- webpackConfig
- .plugin('vue-loader')
- .use(require('vue-loader-v16').VueLoaderPlugin)
- // feature flags <http://link.vuejs.org/feature-flags>
- webpackConfig
- .plugin('feature-flags')
- .use(require('webpack').DefinePlugin, [{
- __VUE_OPTIONS_API__: 'true',
- __VUE_PROD_DEVTOOLS__: 'false'
- }])
- }
- // static assets -----------------------------------------------------------
- webpackConfig.module
- .rule('images')
- .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
- .use('url-loader')
- .loader(require.resolve('url-loader'))
- .options(genUrlLoaderOptions('img'))
- // do not base64-inline SVGs.
- // https://github.com/facebookincubator/create-react-app/pull/1180
- webpackConfig.module
- .rule('svg')
- .test(/\.(svg)(\?.*)?$/)
- .use('file-loader')
- .loader(require.resolve('file-loader'))
- .options({
- name: genAssetSubPath('img')
- })
- webpackConfig.module
- .rule('media')
- .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
- .use('url-loader')
- .loader(require.resolve('url-loader'))
- .options(genUrlLoaderOptions('media'))
- webpackConfig.module
- .rule('fonts')
- .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
- .use('url-loader')
- .loader(require.resolve('url-loader'))
- .options(genUrlLoaderOptions('fonts'))
- // 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()
- // shims
- webpackConfig.node
- .merge({
- // prevent webpack from injecting useless setImmediate polyfill because Vue
- // source contains it (although only uses it if it's native).
- setImmediate: false,
- // process is injected via DefinePlugin, although some 3rd party
- // libraries may require a mock to work properly (#934)
- process: 'mock',
- // prevent webpack from injecting mocks to Node native modules
- // that does not make sense for the client
- dgram: 'empty',
- fs: 'empty',
- net: 'empty',
- tls: 'empty',
- child_process: 'empty'
- })
- const resolveClientEnv = require('../util/resolveClientEnv')
- webpackConfig
- .plugin('define')
- .use(require('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)])
- })
- }
|