vue.config.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. const CompressionWebpackPlugin = require('compression-webpack-plugin')
  2. const VueFilenameInjector = require('@d2-projects/vue-filename-injector')
  3. const ThemeColorReplacer = require('webpack-theme-color-replacer')
  4. const forElementUI = require('webpack-theme-color-replacer/forElementUI')
  5. const { set, each, compact, map, keys } = require('lodash')
  6. const resolve = dir => require('path').join(__dirname, dir)
  7. // Add environment variable
  8. process.env.VUE_APP_VERSION = require('./package.json').version
  9. process.env.VUE_APP_BUILD_TIME = require('dayjs')().format('YYYY-M-D HH:mm:ss')
  10. // Build configuration for multiple pages
  11. const pages = {
  12. index: {
  13. entry: 'src/main.js',
  14. template: 'public/index.html',
  15. filename: 'index.html',
  16. chunks: [
  17. 'manifest',
  18. 'index',
  19. 'chunk-index',
  20. 'chunk-vendor',
  21. 'chunk-common',
  22. 'chunk-vue',
  23. 'chunk-element'
  24. ]
  25. },
  26. mobile: {
  27. entry: 'src.mobile/main.js',
  28. template: 'public/mobile.html',
  29. filename: 'mobile.html',
  30. chunks: [
  31. 'manifest',
  32. 'mobile',
  33. 'chunk-mobile',
  34. 'chunk-vendor',
  35. 'chunk-common',
  36. 'chunk-vue'
  37. ]
  38. }
  39. }
  40. // Set up the external dependency package introduced by the method of using CDN
  41. // For example
  42. // if you set the Axios related link configuration here
  43. // Axios will no longer participate in the packaging during the construction. Finally
  44. // the external link you configured will be used to import Axios in the build result
  45. const cdn = {
  46. // Which external dependencies related to index page are introduced in the form of CDN links
  47. index: [
  48. // {
  49. // name: 'axios',
  50. // library: 'axios',
  51. // js: 'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js',
  52. // css: ''
  53. // }
  54. ],
  55. // Which external dependencies related to mobile page are introduced in the form of CDN links
  56. mobile: [
  57. // {
  58. // name: 'axios',
  59. // library: 'axios',
  60. // js: 'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js',
  61. // css: ''
  62. // }
  63. ]
  64. }
  65. // Set external dependent packages that do not participate in the build
  66. const externals = {}
  67. keys(pages).forEach(name => {
  68. cdn[name].forEach(p => {
  69. externals[p.name] = p.library
  70. })
  71. })
  72. module.exports = {
  73. publicPath: process.env.VUE_APP_PUBLIC_PATH || '/',
  74. lintOnSave: true,
  75. devServer: {
  76. publicPath: process.env.VUE_APP_PUBLIC_PATH || '/',
  77. disableHostCheck: process.env.NODE_ENV === 'development'
  78. },
  79. css: {
  80. loaderOptions: {
  81. sass: {
  82. additionalData: '@use "@/assets/style/public.scss" as *;'
  83. },
  84. less: {
  85. lessOptions: {
  86. modifyVars: {
  87. blue: '#2262AB'
  88. }
  89. }
  90. }
  91. }
  92. },
  93. pages,
  94. configureWebpack: config => {
  95. const configNew = {}
  96. if (process.env.NODE_ENV === 'production') {
  97. configNew.externals = externals
  98. configNew.plugins = [
  99. // gzip
  100. new CompressionWebpackPlugin({
  101. filename: '[path].gz[query]',
  102. test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'),
  103. threshold: 10240,
  104. minRatio: 0.8,
  105. deleteOriginalAssets: false
  106. })
  107. ]
  108. }
  109. return configNew
  110. },
  111. // default: https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-service/lib/config/base.js
  112. chainWebpack: config => {
  113. config.optimization.runtimeChunk({
  114. name: 'manifest'
  115. })
  116. config.optimization.splitChunks({
  117. cacheGroups: {
  118. // External dependencies common to all pages
  119. libs: {
  120. name: 'chunk-vendor',
  121. chunks: 'initial',
  122. minChunks: 1,
  123. test: /[\\/]node_modules[\\/]/,
  124. priority: 1,
  125. reuseExistingChunk: true,
  126. enforce: true
  127. },
  128. // Code common to all pages
  129. common: {
  130. name: 'chunk-common',
  131. chunks: 'initial',
  132. minChunks: 2,
  133. maxInitialRequests: 5,
  134. minSize: 0,
  135. priority: 2,
  136. reuseExistingChunk: true,
  137. enforce: true
  138. },
  139. // External dependencies that are only used by the index page
  140. index: {
  141. name: 'chunk-index',
  142. chunks: 'all',
  143. minChunks: 1,
  144. test: /[\\/]node_modules[\\/](sortablejs|screenfull|nprogress|hotkeys-js|fuse\.js|better-scroll|lowdb|shortid)[\\/]/,
  145. priority: 3,
  146. reuseExistingChunk: true,
  147. enforce: true
  148. },
  149. // External dependencies that are only used by the mobile page
  150. mobile: {
  151. name: 'chunk-mobile',
  152. chunks: 'all',
  153. minChunks: 1,
  154. test: /[\\/]node_modules[\\/](vant)[\\/]/,
  155. priority: 3,
  156. reuseExistingChunk: true,
  157. enforce: true
  158. },
  159. // Vue family packages
  160. vue: {
  161. name: 'chunk-vue',
  162. test: /[\\/]node_modules[\\/](vue|vue-router|vuex)[\\/]/,
  163. chunks: 'all',
  164. priority: 3,
  165. reuseExistingChunk: true,
  166. enforce: true
  167. },
  168. // only element-ui
  169. element: {
  170. name: 'chunk-element',
  171. test: /[\\/]node_modules[\\/]element-ui[\\/]/,
  172. chunks: 'all',
  173. priority: 3,
  174. reuseExistingChunk: true,
  175. enforce: true
  176. }
  177. }
  178. })
  179. // Add the CDN settings to the settings of the htmlwebpackplugin plug-in
  180. keys(pages).forEach(name => {
  181. const packages = cdn[name]
  182. config.plugin(`html-${name}`).tap(options => {
  183. const setting = {
  184. css: compact(map(packages, 'css')),
  185. js: compact(map(packages, 'js'))
  186. }
  187. set(options, '[0].cdn', process.env.NODE_ENV === 'production' ? setting : [])
  188. return options
  189. })
  190. })
  191. // Remove prefetch preload settings for lazy load modules
  192. each(keys(pages), name => {
  193. config.plugins.delete(`prefetch-${name}`)
  194. config.plugins.delete(`preload-${name}`)
  195. })
  196. // webpack-theme-color-replacer
  197. config
  198. .plugin('theme-color-replacer')
  199. .use(ThemeColorReplacer, [{
  200. fileName: 'css/theme-colors.[contenthash:8].css',
  201. matchColors: [
  202. ...forElementUI.getElementUISeries(process.env.VUE_APP_ELEMENT_COLOR) // Element-ui主色系列
  203. ],
  204. externalCssFiles: ['./node_modules/element-ui/lib/theme-chalk/index.css'], // optional, String or string array. Set external css files (such as cdn css) to extract colors.
  205. changeSelector: forElementUI.changeSelector
  206. }])
  207. config
  208. // The development environment sourcemap does not contain column information
  209. .when(process.env.NODE_ENV === 'development',
  210. config => config.devtool('cheap-source-map')
  211. )
  212. // Add file name
  213. .when(
  214. process.env.VUE_APP_SCOURCE_LINK === 'TRUE',
  215. config => VueFilenameInjector(config, {
  216. propName: process.env.VUE_APP_SOURCE_VIEWER_PROP_NAME
  217. })
  218. )
  219. // markdown
  220. config.module
  221. .rule('md')
  222. .test(/\.md$/)
  223. .use('text-loader')
  224. .loader('text-loader')
  225. .end()
  226. // svg
  227. const svgRule = config.module.rule('svg')
  228. svgRule.uses.clear()
  229. svgRule
  230. .include
  231. .add(resolve('src/assets/svg-icons/icons'))
  232. .end()
  233. .use('svg-sprite-loader')
  234. .loader('svg-sprite-loader')
  235. .options({
  236. symbolId: 'd2-[name]'
  237. })
  238. .end()
  239. // image exclude
  240. const imagesRule = config.module.rule('images')
  241. imagesRule
  242. .test(/\.(png|jpe?g|gif|webp|svg)(\?.*)?$/)
  243. .exclude
  244. .add(resolve('src/assets/svg-icons/icons'))
  245. .end()
  246. // set alias
  247. config.resolve.alias
  248. .set('@.mobile', resolve('src.mobile'))
  249. },
  250. // 不输出 map 文件
  251. productionSourceMap: false,
  252. // i18n
  253. pluginOptions: {
  254. i18n: {
  255. locale: 'zh-chs',
  256. fallbackLocale: 'en',
  257. localeDir: 'locales',
  258. enableInSFC: true
  259. }
  260. }
  261. }