vue.config.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. const path = require('path');
  2. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  3. const CompressionWebpackPlugin = require('compression-webpack-plugin');
  4. const CopyWebpackPlugin = require('copy-webpack-plugin');
  5. // const ThemeColorReplacer = require('webpack-theme-color-replacer');
  6. // const forElementUI = require('webpack-theme-color-replacer/forElementUI');
  7. const { chain, set, each } = require('lodash');
  8. const package = require('./package.json');
  9. const cdnDependencies = process.env.VUE_APP_CDN === 'on' ? require('./dependencies-cdn') : [];
  10. const isProduction = process.env.NODE_ENV === 'production';
  11. // 拼接路径
  12. const resolve = dir => path.join(__dirname, dir);
  13. // 版本 & 构建时间
  14. const version = package.version;
  15. const nowDate = new Date();
  16. const buildDate = `${nowDate.getFullYear()}-${nowDate.getMonth() +
  17. 1}-${nowDate.getDate()} ${nowDate.getHours()}:${nowDate.getMinutes()}`;
  18. // 增加环境变量
  19. process.env.VUE_APP_VERSION = version;
  20. process.env.VUE_APP_BUILD_TIME = buildDate;
  21. process.env.VUE_APP_BUILD_INFO = `版本: ${version}, 构建日期: ${buildDate}`;
  22. process.env.VUE_APP_TITLE = process.env.VUE_APP_TITLE || package.name;
  23. // 基础路径
  24. const publicPath = `/adm_comp`; //process.env.VUE_APP_PUBLIC_PATH || '/';
  25. const assetsDir = `./static`;
  26. const assetsPath = _path => `${assetsDir}/${_path}`;
  27. // 设置不参与构建的库
  28. const externals = {};
  29. cdnDependencies.forEach(pkg => {
  30. externals[pkg.name] = pkg.library;
  31. });
  32. // 引入文件的 cdn 链接
  33. const cdn = {
  34. css: cdnDependencies.map(e => e.css).filter(e => e),
  35. js: cdnDependencies.map(e => e.js).filter(e => e)
  36. };
  37. // 多页配置, 默认未开启,如需要请参考 https://cli.vuejs.org/zh/config/#pages
  38. const pages = undefined;
  39. // const pages = {
  40. // index: './src/main.js',
  41. // subpage: './src/subpage.js'
  42. // }
  43. module.exports = {
  44. publicPath,
  45. assetsDir,
  46. lintOnSave: true,
  47. devServer: {
  48. hot: false,
  49. publicPath, // 和 publicPath 保持一致
  50. disableHostCheck: !isProduction, // 关闭 host check,方便使用 ngrok 之类的内网转发工具
  51. port: 4200,
  52. proxy: {
  53. '': {
  54. // 目标 API 地址 需要代理的服务器
  55. target: 'http://192.168.58.127:9012',
  56. // 如果要代理 websocket
  57. ws: true,
  58. // 是否允许跨域
  59. changeOrigin: true,
  60. pathRewrite: {
  61. '^/api': ''
  62. }
  63. }
  64. }
  65. },
  66. css: {
  67. extract: true,
  68. loaderOptions: {
  69. // 设置 scss 公用变量
  70. sass: {
  71. prependData: "@import './src/styles/var.scss';"
  72. }
  73. }
  74. },
  75. // pages,
  76. configureWebpack: config => {
  77. config.entry.app = ['./src/polyfills.ts', './src/main.ts'];
  78. const configNew = {
  79. plugins: [
  80. // copy custom static assets
  81. new CopyWebpackPlugin([
  82. {
  83. from: resolve(assetsDir),
  84. to: assetsDir,
  85. ignore: ['.*']
  86. }
  87. ])
  88. ]
  89. };
  90. if (isProduction) {
  91. configNew.externals = externals;
  92. configNew.output = {
  93. filename: assetsPath('js/[name].[contenthash:8].js'),
  94. chunkFilename: assetsPath('js/[id].[contenthash:8].js')
  95. };
  96. // gzip
  97. if (process.env.GZIP === 'on') {
  98. configNew.plugins.push(
  99. new CompressionWebpackPlugin({
  100. filename: '[path].gz[query]',
  101. test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'),
  102. threshold: 10240,
  103. minRatio: 0.8,
  104. deleteOriginalAssets: false
  105. })
  106. );
  107. }
  108. }
  109. return configNew;
  110. },
  111. // 默认设置: https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-service/lib/config/base.js
  112. chainWebpack: config => {
  113. if (isProduction) {
  114. config.plugin('extract-css').use(MiniCssExtractPlugin, [
  115. {
  116. filename: assetsPath('css/[name].[contenthash:8].css'),
  117. chunkFilename: assetsPath('css/[id].[contenthash:8].css')
  118. }
  119. ]);
  120. // 多页时优化代码分割
  121. if (pages) {
  122. config.optimization.splitChunks({
  123. chunks: 'all',
  124. // 大于30KB才单独分离成chunk
  125. minSize: 30000,
  126. name: true,
  127. cacheGroups: {
  128. default: {
  129. priority: -20,
  130. // minChunks: 2,
  131. reuseExistingChunk: true
  132. },
  133. core: {
  134. name: 'core',
  135. test: /[\\/]src[\\/](core|shared)[\\/]/,
  136. chunks: 'initial',
  137. priority: -10,
  138. reuseExistingChunk: true
  139. },
  140. vendors: {
  141. name: 'vendors',
  142. test: /[\\/]node_modules[\\/]/,
  143. priority: 0,
  144. chunks: 'initial' // 只打包初始时依赖的第三方
  145. }
  146. }
  147. });
  148. }
  149. }
  150. /**
  151. * 添加 CDN 参数到 htmlWebpackPlugin 配置中
  152. * 已适配多页
  153. */
  154. const htmlPluginNames = chain(pages)
  155. .keys()
  156. .map(page => 'html-' + page)
  157. .value();
  158. const targetHtmlPluginNames = htmlPluginNames.length ? htmlPluginNames : ['html'];
  159. each(targetHtmlPluginNames, name => {
  160. config.plugin(name).tap(options => {
  161. set(options, '[0].cdn', isProduction ? cdn : []);
  162. return options;
  163. });
  164. });
  165. /**
  166. * 删除懒加载模块的 prefetch preload, 降低带宽压力
  167. * https://cli.vuejs.org/zh/guide/html-and-static-assets.html#prefetch
  168. * https://cli.vuejs.org/zh/guide/html-and-static-assets.html#preload
  169. * 而且预渲染时生成的 prefetch 标签是 modern 版本的,低版本浏览器是不需要的
  170. */
  171. config.plugins.delete('prefetch').delete('preload');
  172. // 解决 cli3 热更新失效 https://github.com/vuejs/vue-cli/issues/1559
  173. config.resolve.symlinks(true);
  174. // config.plugin('theme-color-replacer').use(ThemeColorReplacer, [
  175. // {
  176. // fileName: `${assetsDir}/css/theme-colors.[contenthash:8].css`,
  177. // matchColors: [
  178. // ...forElementUI.getElementUISeries(process.env.VUE_APP_ELEMENT_COLOR) // Element-UI主色系列
  179. // ],
  180. // 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.
  181. // changeSelector: forElementUI.changeSelector
  182. // }
  183. // ]);
  184. config
  185. // 开发环境 sourcemap 不包含列信息
  186. .when(!isProduction, config => config.devtool('cheap-source-map'));
  187. // markdown
  188. config.module
  189. .rule('md')
  190. .test(/\.md$/)
  191. .use('text-loader')
  192. .loader('text-loader')
  193. .end();
  194. // svg
  195. const svgRule = config.module.rule('svg');
  196. svgRule.uses.clear();
  197. svgRule.include
  198. .add(resolve('src/assets/svg/icons'))
  199. .end()
  200. .use('svg-sprite-loader')
  201. .loader('svg-sprite-loader')
  202. .options({
  203. symbolId: 'tui-icon-[name]'
  204. })
  205. .end();
  206. // image exclude
  207. const imagesRule = config.module.rule('images');
  208. imagesRule
  209. .test(/\.(png|jpe?g|gif|webp|svg)(\?.*)?$/)
  210. .exclude.add(resolve('src/assets/svg/icons'))
  211. .end();
  212. // 重新设置 alias
  213. const paths = require('./tsconfig.json').compilerOptions.paths;
  214. if (!isProduction && process.env.LOCAL_ALIAS) {
  215. const localAlias = JSON.parse(process.env.LOCAL_ALIAS);
  216. Object.assign(paths, localAlias);
  217. }
  218. Object.keys(paths).forEach(key => {
  219. config.resolve.alias.set(key.replace('/*', ''), resolve(paths[key][0].replace('/*', '')));
  220. });
  221. // 分析工具
  222. if (process.env.npm_config_report) {
  223. config.plugin('webpack-bundle-analyzer').use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin);
  224. }
  225. },
  226. // 不输出 map 文件
  227. productionSourceMap: false,
  228. pluginOptions: {}
  229. };