/** * @created by pan * @updated by helin3 2019-04-06 * @description vue-cli 配置 */ "use strict"; const path = require("path"); const pkg = require("./package.json"); const webpack = require("webpack"); const defaultSettings = require("./src/config"); const glob = require("glob"); const PAGES_PATH = path.resolve(__dirname, "./src/pages"); const name = defaultSettings.title; // 网页浏览器标题 const publicPath = process.env.VUE_APP_PUBLIC_PATH; // 部署路径 const devPort = process.env.VUE_APP_DEV_PORT; // dev默认端口号,启动被占用时自动+1 const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); const resolve = (dir) => path.join(__dirname, dir); // 当前目录,即项目根目录解析 const pages = {}; // 多入口列表 /** * 开发模式,获取代理配置 * 注: 若配置项VUE_APP_BASE_API包含协议、域名[IP]、端口[可选],开发模式则默认配置代理 */ const getProxyConfig = () => { const devEnv = process.env.NODE_ENV === "development"; // 开发环境 const baseApi = process.env.VUE_APP_BASE_API; // 应用服务前缀URL let proxyPrefix = process.env.VUE_APP_PROXY_PREFIX; // 代理API前缀 const match = /^(https?:\/\/[0-9a-z.]+)(:[0-9]+)?([/0-9a-z.]+)?/i; // 匹配URL(协议+域名+端口) const matchResult = match.exec(baseApi); let devServerProxy = {}; // 配置的代理对象,默认false,为空 if (devEnv && matchResult) { // VUE_APP_BASE_API代理配置演示,/dev-proxy-api/xxx-api/* => https://172.16.20.92:8102/xxx-api/* // 详见: https://cli.vuejs.org/config/#devserver-proxy // 可数组配置多个 if (Object.prototype.toString.call(proxyPrefix) === "[object String]") { proxyPrefix = proxyPrefix.split(","); } if (Array.isArray(proxyPrefix)) { proxyPrefix.forEach((item) => { devServerProxy[item] = { target: `${matchResult[1] + matchResult[2]}`, // 协议+域名 changeOrigin: true, // pathRewrite: { // ['^' + item]: '' // } }; }); } } devServerProxy = JSON.stringify(devServerProxy) == "{}" ? false : devServerProxy; console.log("配置代理", devServerProxy); return devServerProxy; }; console.log(name, pkg.version); // 多页应用配置 if (defaultSettings.mpa) { //配置 pages 目录下的多页面,通过循环获取每一个 page 文件夹下的 html 和 js glob.sync(PAGES_PATH + "/*/main.js").forEach((filePath) => { const pageName = path.basename(path.dirname(filePath)); pages[pageName] = { entry: filePath, template: path.dirname(filePath) + "/index.html", filename: `${pageName}.html`, chunks: ["chunk-vendors", pageName, `manifest.${pageName}`], }; }); } // 增加系统默认的index主页 pages["index"] = { entry: "src/main.js", template: "public/index.html", filename: `index.html`, chunks: ["chunk-vendors", "index", "manifest.index"], }; // 详细配置见:https://cli.vuejs.org/config/ const exportsConfig = { /** * APP应用若计划部署在应用服务器子目录,则需要设置publicPath, * 例如:你计划部署在GitHub Pages上,访问路径为:https://your.github.io/app/,则你此处应配置为:'/app/' * 默认配置为根:'/' */ parallel: true, publicPath: publicPath, outputDir: "dist", assetsDir: "static", lintOnSave: false, // lintOnSave: process.env.NODE_ENV === 'development' ? 'error' : false, productionSourceMap: process.env.NODE_ENV === "development" ? true : false, runtimeCompiler: true, pages: pages, devServer: { allowedHosts: "all", port: devPort, open: false, client: { // https://webpack.docschina.org/configuration/dev-server/#overlay overlay: false, //禁止:当出现编译错误或警告时,在浏览器中显示全屏覆盖 }, proxy: getProxyConfig(), }, configureWebpack(config) { // provide the app's title in webpack's name field, so that // it can be accessed in index.html to inject the correct title. return { name: name, resolve: { alias: { "@": resolve("src"), assets: resolve("src/assets"), static: resolve("public/static"), // '(\\.md|demo_index\\.html)$': false [path.resolve(__dirname, "src/views/content/guide/readme.md")]: false, }, modules: [path.resolve(__dirname, "src")], extensions: [".js", ".jsx", ".json"], fallback: { path: require.resolve("path-browserify"), }, }, output: { filename: "[name].[chunkhash:8].js", }, externals: { // 需要将对应的js文件直接在index.html中引入 // 为兼容多入口引入公共文件不一致 vue: "Vue", "vue-router": "window.VueRouter || {}", vuex: "window.Vuex || {}", axios: "window.axios || {}", "xy-utils": "window.XYUTILS || {}", xlsx: "window.XLSX || {}", echarts: "window.echarts || {}", jquery: "window.jQuery || {}", fs: require("fs"), }, cache: { // 开启持久化缓存 type: "filesystem", buildDependencies: { config: [__filename], }, }, ignoreWarnings: [(warning, compilation) => true], // 消除警报 optimization: { // minimize: true, // 关闭 CSS 压缩 splitChunks: { chunks: "all", minSize: 30 * 1024, maxSize: 500 * 1024, minRemainingSize: 0, minChunks: 2, maxAsyncRequests: 10, maxInitialRequests: 8, enforceSizeThreshold: 50000, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, //控制此缓存组选择的模块。省略它将选择所有模块。它可以匹配绝对模块资源路径或块名称。匹配块名称时,将选择块中的所有模块。 name: "vendors", minChunks: 2, enforce: true, priority: 100, chunks: "initial", }, yuwpUi: { test: /[\/]node_modules[\/]_?yuwp-ui(.*)/, priority: 120, name: "yuwp-ui", reuseExistingChunk: true, enforce: true, }, // 分割常用的第三方库 antv: { name: "chunk-antv", priority: 120, test: /[\\/]node_modules[\\/]_?@antv(.*)/, reuseExistingChunk: true, enforce: true, }, // 分割常用的第三方库 monacoVendors: { test: /[\\/]node_modules[\\/]_?monaco-editor(.*)/, priority: 120, name: "monaco-vendors", reuseExistingChunk: true, chunks: "all", enforce: true, }, "async-commons": { // 异步加载公共包、组件等 chunks: "async", minChunks: 2, name: "async-commons", priority: 10, chunks: "initial", enforce: true, }, default: { name: "default", minChunks: 2, priority: 10, chunks: "initial", reuseExistingChunk: true, //如果当前块包含已经从主包中分离出来的模块,那么该模块将被重用,而不是生成新的模块 enforce: true, }, }, }, }, }; }, chainWebpack(config) { // 单页时删除预加载 config.plugins.delete("preload"); config.plugins.delete("prefetch"); // 多入口时删除对应的预加载 vue-cli删除预加载时,匹配各入口名称 var keys = Object.keys(pages); keys.forEach((k) => { config.plugins.delete(`prefetch-${k}`); config.plugins.delete(`preload-${k}`); }); // if (process.env.IS_ANALYZ) { // config // .plugin("webpack-bundle-analyzer") // .use(require("webpack-bundle-analyzer").BundleAnalyzerPlugin); // } // if (process.env.NODE_ENV === "production") { // config // .plugin("webpack-bundle-analyzer") // .use(require("webpack-bundle-analyzer").BundleAnalyzerPlugin) // .end(); // } // 修复HMR config.resolve.symlinks(true); config .plugin("ignore") .use( new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn$/) ); // config.plugin("html").tap(args => { // // 修复 Lazy loading routes Error // args[0].chunksSortMode = "none"; // // html中添加cdn // // args[0].cdn = cdn; // return args; // }) // set svg-sprite-loader config.module .rule("svg") .exclude.add(resolve("src/assets/common/icons")) .end(); config.module .rule("icons") .test(/\.svg$/) .include.add(resolve("src/assets/common/icons")) .end() .use("svg-sprite-loader") .loader("svg-sprite-loader") .options({ symbolId: "icon-[name]", }) .end(); // set preserveWhitespace config.module .rule("vue") .use("vue-loader") .loader("vue-loader") .tap((options) => { options.compilerOptions.preserveWhitespace = true; return options; }) .end(); // 图片压缩 // config.module // .rule("image-webpack-loader") // .test(/\.(gif|png|jpe?g|svg)$/i) // .use("file-loader") // .loader("image-webpack-loader") // .tap(() => ({ // disable: process.env.NODE_ENV !== "production", // })) // .end(); // 字体文件处理 // config.module // .rule("url-loader") // .test(/\.(eot|woff2?|ttf)$/) // .use("url-loader") // .loader("url-loader") // .end(); config.when( process.env.NODE_ENV === "development", // config => config.devtool('cheap-source-map') (config) => config.devtool("eval-source-map") ); }, // 配置高于chainWebpack中关于 css loader 的配置 css: { // 是否使用 css 分离插件 ExtractTextPlugin,采用独立样式文件载入,不采用