vue.config.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /**
  2. * @created by pan
  3. * @updated by helin3 2019-04-06
  4. * @description vue-cli 配置
  5. */
  6. "use strict";
  7. const path = require("path");
  8. const pkg = require("./package.json");
  9. const webpack = require("webpack");
  10. const defaultSettings = require("./src/config");
  11. const glob = require("glob");
  12. const PAGES_PATH = path.resolve(__dirname, "./src/pages");
  13. const name = defaultSettings.title; // 网页浏览器标题
  14. const publicPath = process.env.VUE_APP_PUBLIC_PATH; // 部署路径
  15. const devPort = process.env.VUE_APP_DEV_PORT; // dev默认端口号,启动被占用时自动+1
  16. const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
  17. const resolve = (dir) => path.join(__dirname, dir); // 当前目录,即项目根目录解析
  18. const pages = {}; // 多入口列表
  19. /**
  20. * 开发模式,获取代理配置
  21. * 注: 若配置项VUE_APP_BASE_API包含协议、域名[IP]、端口[可选],开发模式则默认配置代理
  22. */
  23. const getProxyConfig = () => {
  24. const devEnv = process.env.NODE_ENV === "development"; // 开发环境
  25. const baseApi = process.env.VUE_APP_BASE_API; // 应用服务前缀URL
  26. let proxyPrefix = process.env.VUE_APP_PROXY_PREFIX; // 代理API前缀
  27. const match = /^(https?:\/\/[0-9a-z.]+)(:[0-9]+)?([/0-9a-z.]+)?/i; // 匹配URL(协议+域名+端口)
  28. const matchResult = match.exec(baseApi);
  29. let devServerProxy = {}; // 配置的代理对象,默认false,为空
  30. if (devEnv && matchResult) {
  31. // VUE_APP_BASE_API代理配置演示,/dev-proxy-api/xxx-api/* => https://172.16.20.92:8102/xxx-api/*
  32. // 详见: https://cli.vuejs.org/config/#devserver-proxy
  33. // 可数组配置多个
  34. if (Object.prototype.toString.call(proxyPrefix) === "[object String]") {
  35. proxyPrefix = proxyPrefix.split(",");
  36. }
  37. if (Array.isArray(proxyPrefix)) {
  38. proxyPrefix.forEach((item) => {
  39. devServerProxy[item] = {
  40. target: `${matchResult[1] + matchResult[2]}`, // 协议+域名
  41. changeOrigin: true,
  42. // pathRewrite: {
  43. // ['^' + item]: ''
  44. // }
  45. };
  46. });
  47. }
  48. }
  49. devServerProxy =
  50. JSON.stringify(devServerProxy) == "{}" ? false : devServerProxy;
  51. console.log("配置代理", devServerProxy);
  52. return devServerProxy;
  53. };
  54. console.log(name, pkg.version);
  55. // 多页应用配置
  56. if (defaultSettings.mpa) {
  57. //配置 pages 目录下的多页面,通过循环获取每一个 page 文件夹下的 html 和 js
  58. glob.sync(PAGES_PATH + "/*/main.js").forEach((filePath) => {
  59. const pageName = path.basename(path.dirname(filePath));
  60. pages[pageName] = {
  61. entry: filePath,
  62. template: path.dirname(filePath) + "/index.html",
  63. filename: `${pageName}.html`,
  64. chunks: ["chunk-vendors", pageName, `manifest.${pageName}`],
  65. };
  66. });
  67. }
  68. // 增加系统默认的index主页
  69. pages["index"] = {
  70. entry: "src/main.js",
  71. template: "public/index.html",
  72. filename: `index.html`,
  73. chunks: ["chunk-vendors", "index", "manifest.index"],
  74. };
  75. // 详细配置见:https://cli.vuejs.org/config/
  76. const exportsConfig = {
  77. /**
  78. * APP应用若计划部署在应用服务器子目录,则需要设置publicPath,
  79. * 例如:你计划部署在GitHub Pages上,访问路径为:https://your.github.io/app/,则你此处应配置为:'/app/'
  80. * 默认配置为根:'/'
  81. */
  82. parallel: true,
  83. publicPath: publicPath,
  84. outputDir: "dist",
  85. assetsDir: "static",
  86. lintOnSave: false,
  87. // lintOnSave: process.env.NODE_ENV === 'development' ? 'error' : false,
  88. productionSourceMap: process.env.NODE_ENV === "development" ? true : false,
  89. runtimeCompiler: true,
  90. pages: pages,
  91. devServer: {
  92. allowedHosts: "all",
  93. port: devPort,
  94. open: false,
  95. client: {
  96. // https://webpack.docschina.org/configuration/dev-server/#overlay
  97. overlay: false, //禁止:当出现编译错误或警告时,在浏览器中显示全屏覆盖
  98. },
  99. proxy: getProxyConfig(),
  100. },
  101. configureWebpack(config) {
  102. // provide the app's title in webpack's name field, so that
  103. // it can be accessed in index.html to inject the correct title.
  104. return {
  105. name: name,
  106. resolve: {
  107. alias: {
  108. "@": resolve("src"),
  109. assets: resolve("src/assets"),
  110. static: resolve("public/static"),
  111. // '(\\.md|demo_index\\.html)$': false
  112. [path.resolve(__dirname, "src/views/content/guide/readme.md")]: false,
  113. },
  114. modules: [path.resolve(__dirname, "src")],
  115. extensions: [".js", ".jsx", ".json"],
  116. fallback: {
  117. path: require.resolve("path-browserify"),
  118. },
  119. },
  120. output: {
  121. filename: "[name].[chunkhash:8].js",
  122. },
  123. externals: {
  124. // 需要将对应的js文件直接在index.html中引入
  125. // 为兼容多入口引入公共文件不一致
  126. vue: "Vue",
  127. "vue-router": "window.VueRouter || {}",
  128. vuex: "window.Vuex || {}",
  129. axios: "window.axios || {}",
  130. "xy-utils": "window.XYUTILS || {}",
  131. xlsx: "window.XLSX || {}",
  132. echarts: "window.echarts || {}",
  133. jquery: "window.jQuery || {}",
  134. fs: require("fs"),
  135. },
  136. cache: {
  137. // 开启持久化缓存
  138. type: "filesystem",
  139. buildDependencies: {
  140. config: [__filename],
  141. },
  142. },
  143. ignoreWarnings: [(warning, compilation) => true], // 消除警报
  144. optimization: {
  145. // minimize: true, // 关闭 CSS 压缩
  146. splitChunks: {
  147. chunks: "all",
  148. minSize: 30 * 1024,
  149. maxSize: 500 * 1024,
  150. minRemainingSize: 0,
  151. minChunks: 2,
  152. maxAsyncRequests: 10,
  153. maxInitialRequests: 8,
  154. enforceSizeThreshold: 50000,
  155. cacheGroups: {
  156. vendors: {
  157. test: /[\\/]node_modules[\\/]/, //控制此缓存组选择的模块。省略它将选择所有模块。它可以匹配绝对模块资源路径或块名称。匹配块名称时,将选择块中的所有模块。
  158. name: "vendors",
  159. minChunks: 2,
  160. enforce: true,
  161. priority: 100,
  162. chunks: "initial",
  163. },
  164. yuwpUi: {
  165. test: /[\/]node_modules[\/]_?yuwp-ui(.*)/,
  166. priority: 120,
  167. name: "yuwp-ui",
  168. reuseExistingChunk: true,
  169. enforce: true,
  170. },
  171. // 分割常用的第三方库
  172. antv: {
  173. name: "chunk-antv",
  174. priority: 120,
  175. test: /[\\/]node_modules[\\/]_?@antv(.*)/,
  176. reuseExistingChunk: true,
  177. enforce: true,
  178. },
  179. // 分割常用的第三方库
  180. monacoVendors: {
  181. test: /[\\/]node_modules[\\/]_?monaco-editor(.*)/,
  182. priority: 120,
  183. name: "monaco-vendors",
  184. reuseExistingChunk: true,
  185. chunks: "all",
  186. enforce: true,
  187. },
  188. "async-commons": {
  189. // 异步加载公共包、组件等
  190. chunks: "async",
  191. minChunks: 2,
  192. name: "async-commons",
  193. priority: 10,
  194. chunks: "initial",
  195. enforce: true,
  196. },
  197. default: {
  198. name: "default",
  199. minChunks: 2,
  200. priority: 10,
  201. chunks: "initial",
  202. reuseExistingChunk: true, //如果当前块包含已经从主包中分离出来的模块,那么该模块将被重用,而不是生成新的模块
  203. enforce: true,
  204. },
  205. },
  206. },
  207. },
  208. };
  209. },
  210. chainWebpack(config) {
  211. // 单页时删除预加载
  212. config.plugins.delete("preload");
  213. config.plugins.delete("prefetch");
  214. // 多入口时删除对应的预加载 vue-cli删除预加载时,匹配各入口名称
  215. var keys = Object.keys(pages);
  216. keys.forEach((k) => {
  217. config.plugins.delete(`prefetch-${k}`);
  218. config.plugins.delete(`preload-${k}`);
  219. });
  220. // if (process.env.IS_ANALYZ) {
  221. // config
  222. // .plugin("webpack-bundle-analyzer")
  223. // .use(require("webpack-bundle-analyzer").BundleAnalyzerPlugin);
  224. // }
  225. // if (process.env.NODE_ENV === "production") {
  226. // config
  227. // .plugin("webpack-bundle-analyzer")
  228. // .use(require("webpack-bundle-analyzer").BundleAnalyzerPlugin)
  229. // .end();
  230. // }
  231. // 修复HMR
  232. config.resolve.symlinks(true);
  233. config
  234. .plugin("ignore")
  235. .use(
  236. new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn$/)
  237. );
  238. // config.plugin("html").tap(args => {
  239. // // 修复 Lazy loading routes Error
  240. // args[0].chunksSortMode = "none";
  241. // // html中添加cdn
  242. // // args[0].cdn = cdn;
  243. // return args;
  244. // })
  245. // set svg-sprite-loader
  246. config.module
  247. .rule("svg")
  248. .exclude.add(resolve("src/assets/common/icons"))
  249. .end();
  250. config.module
  251. .rule("icons")
  252. .test(/\.svg$/)
  253. .include.add(resolve("src/assets/common/icons"))
  254. .end()
  255. .use("svg-sprite-loader")
  256. .loader("svg-sprite-loader")
  257. .options({
  258. symbolId: "icon-[name]",
  259. })
  260. .end();
  261. // set preserveWhitespace
  262. config.module
  263. .rule("vue")
  264. .use("vue-loader")
  265. .loader("vue-loader")
  266. .tap((options) => {
  267. options.compilerOptions.preserveWhitespace = true;
  268. return options;
  269. })
  270. .end();
  271. // 图片压缩
  272. // config.module
  273. // .rule("image-webpack-loader")
  274. // .test(/\.(gif|png|jpe?g|svg)$/i)
  275. // .use("file-loader")
  276. // .loader("image-webpack-loader")
  277. // .tap(() => ({
  278. // disable: process.env.NODE_ENV !== "production",
  279. // }))
  280. // .end();
  281. // 字体文件处理
  282. // config.module
  283. // .rule("url-loader")
  284. // .test(/\.(eot|woff2?|ttf)$/)
  285. // .use("url-loader")
  286. // .loader("url-loader")
  287. // .end();
  288. config.when(
  289. process.env.NODE_ENV === "development",
  290. // config => config.devtool('cheap-source-map')
  291. (config) => config.devtool("eval-source-map")
  292. );
  293. },
  294. // 配置高于chainWebpack中关于 css loader 的配置
  295. css: {
  296. // 是否使用 css 分离插件 ExtractTextPlugin,采用独立样式文件载入,不采用 <style> 方式内联至 html 文件中
  297. extract: process.env.NODE_ENV !== "development",
  298. // 是否构建样式地图,false 将提高构建速度
  299. sourceMap: false,
  300. loaderOptions: {
  301. sass: {
  302. implementation: require("sass"), // This line must in sass option
  303. // additionalData: `@import '~@/views/content/daa/testManager/CheckDialog/index.scss';`
  304. },
  305. css: {},
  306. },
  307. },
  308. };
  309. module.exports = exportsConfig;