base.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. module.exports = (api, options) => {
  2. api.chainWebpack(webpackConfig => {
  3. const isLegacyBundle = process.env.VUE_CLI_MODERN_MODE && !process.env.VUE_CLI_MODERN_BUILD
  4. const resolveLocal = require('../util/resolveLocal')
  5. const getAssetPath = require('../util/getAssetPath')
  6. const inlineLimit = 4096
  7. const genAssetSubPath = dir => {
  8. return getAssetPath(
  9. options,
  10. `${dir}/[name]${options.filenameHashing ? '.[hash:8]' : ''}.[ext]`
  11. )
  12. }
  13. const genUrlLoaderOptions = dir => {
  14. return {
  15. limit: inlineLimit,
  16. // use explicit fallback to avoid regression in url-loader>=1.1.0
  17. fallback: {
  18. loader: 'file-loader',
  19. options: {
  20. name: genAssetSubPath(dir)
  21. }
  22. }
  23. }
  24. }
  25. webpackConfig
  26. .mode('development')
  27. .context(api.service.context)
  28. .entry('app')
  29. .add('./src/main.js')
  30. .end()
  31. .output
  32. .path(api.resolve(options.outputDir))
  33. .filename(isLegacyBundle ? '[name]-legacy.js' : '[name].js')
  34. .publicPath(options.publicPath)
  35. webpackConfig.resolve
  36. .extensions
  37. .merge(['.mjs', '.js', '.jsx', '.vue', '.json', '.wasm'])
  38. .end()
  39. .modules
  40. .add('node_modules')
  41. .add(api.resolve('node_modules'))
  42. .add(resolveLocal('node_modules'))
  43. .end()
  44. .alias
  45. .set('@', api.resolve('src'))
  46. .set(
  47. 'vue$',
  48. options.runtimeCompiler
  49. ? 'vue/dist/vue.esm.js'
  50. : 'vue/dist/vue.runtime.esm.js'
  51. )
  52. webpackConfig.resolveLoader
  53. .modules
  54. .add('node_modules')
  55. .add(api.resolve('node_modules'))
  56. .add(resolveLocal('node_modules'))
  57. webpackConfig.module
  58. .noParse(/^(vue|vue-router|vuex|vuex-router-sync)$/)
  59. // js is handled by cli-plugin-babel ---------------------------------------
  60. // vue-loader --------------------------------------------------------------
  61. const vueLoaderCacheConfig = api.genCacheConfig('vue-loader', {
  62. 'vue-loader': require('vue-loader/package.json').version,
  63. /* eslint-disable-next-line node/no-extraneous-require */
  64. '@vue/component-compiler-utils': require('@vue/component-compiler-utils/package.json').version,
  65. 'vue-template-compiler': require('vue-template-compiler/package.json').version
  66. })
  67. webpackConfig.module
  68. .rule('vue')
  69. .test(/\.vue$/)
  70. .use('cache-loader')
  71. .loader('cache-loader')
  72. .options(vueLoaderCacheConfig)
  73. .end()
  74. .use('vue-loader')
  75. .loader('vue-loader')
  76. .options(Object.assign({
  77. compilerOptions: {
  78. preserveWhitespace: false
  79. }
  80. }, vueLoaderCacheConfig))
  81. webpackConfig
  82. .plugin('vue-loader')
  83. .use(require('vue-loader/lib/plugin'))
  84. // static assets -----------------------------------------------------------
  85. webpackConfig.module
  86. .rule('images')
  87. .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
  88. .use('url-loader')
  89. .loader('url-loader')
  90. .options(genUrlLoaderOptions('img'))
  91. // do not base64-inline SVGs.
  92. // https://github.com/facebookincubator/create-react-app/pull/1180
  93. webpackConfig.module
  94. .rule('svg')
  95. .test(/\.(svg)(\?.*)?$/)
  96. .use('file-loader')
  97. .loader('file-loader')
  98. .options({
  99. name: genAssetSubPath('img')
  100. })
  101. webpackConfig.module
  102. .rule('media')
  103. .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
  104. .use('url-loader')
  105. .loader('url-loader')
  106. .options(genUrlLoaderOptions('media'))
  107. webpackConfig.module
  108. .rule('fonts')
  109. .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
  110. .use('url-loader')
  111. .loader('url-loader')
  112. .options(genUrlLoaderOptions('fonts'))
  113. // Other common pre-processors ---------------------------------------------
  114. webpackConfig.module
  115. .rule('pug')
  116. .test(/\.pug$/)
  117. .oneOf('pug-vue')
  118. .resourceQuery(/vue/)
  119. .use('pug-plain-loader')
  120. .loader('pug-plain-loader')
  121. .end()
  122. .end()
  123. .oneOf('pug-template')
  124. .use('raw')
  125. .loader('raw-loader')
  126. .end()
  127. .use('pug-plain')
  128. .loader('pug-plain-loader')
  129. .end()
  130. .end()
  131. // shims
  132. webpackConfig.node
  133. .merge({
  134. // prevent webpack from injecting useless setImmediate polyfill because Vue
  135. // source contains it (although only uses it if it's native).
  136. setImmediate: false,
  137. // prevent webpack from injecting mocks to Node native modules
  138. // that does not make sense for the client
  139. dgram: 'empty',
  140. fs: 'empty',
  141. net: 'empty',
  142. tls: 'empty',
  143. child_process: 'empty'
  144. })
  145. const resolveClientEnv = require('../util/resolveClientEnv')
  146. webpackConfig
  147. .plugin('define')
  148. .use(require('webpack/lib/DefinePlugin'), [
  149. resolveClientEnv(options)
  150. ])
  151. webpackConfig
  152. .plugin('case-sensitive-paths')
  153. .use(require('case-sensitive-paths-webpack-plugin'))
  154. // friendly error plugin displays very confusing errors when webpack
  155. // fails to resolve a loader, so we provide custom handlers to improve it
  156. const { transformer, formatter } = require('../util/resolveLoaderError')
  157. webpackConfig
  158. .plugin('friendly-errors')
  159. .use(require('@soda/friendly-errors-webpack-plugin'), [{
  160. additionalTransformers: [transformer],
  161. additionalFormatters: [formatter]
  162. }])
  163. })
  164. }