// 是否为生产环境 const isProduction = process.env.NODE_ENV !== 'development' // gzip压缩 const CompressionWebpackPlugin = require('compression-webpack-plugin') const { HashedModuleIdsPlugin } = require('webpack') // path引入 const path = require('path') // path.join(__dirname)设置绝对路径 function resolve(dir) { return path.join(__dirname, dir) } // 打包输出地址 function publicPath() { const build_path = process.env.npm_package_scripts_build.indexOf('--build_path') !== -1 && process.env.npm_package_scripts_build.split('--build_path')[1].trim() if (build_path) { return '/' + build_path + '/' } else { return './' } } // 本地环境是否需要使用cdn const devNeedCdn = true // cdn链接 const cdn = { // cdn:模块名称和模块作用域命名(对应window里面挂载的变量名称) externals: { 'echarts': 'echarts' // vue: 'Vue', // vuex: 'Vuex', // 'vue-router': 'VueRouter', // 'marked': 'marked', // 'highlight.js': 'hljs', // 'nprogress': 'NProgress', // 'axios': 'axios' } // cdn的css链接 // css: [ // 'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css' // ], // // cdn的js链接 // js: [ // 'https://cdn.bootcss.com/vue/2.6.10/vue.min.js', // 'https://cdn.bootcss.com/vuex/3.1.2/vuex.min.js', // 'https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js', // 'https://cdn.bootcss.com/marked/0.8.0/marked.min.js', // 'https://cdn.bootcss.com/highlight.js/9.18.1/highlight.min.js', // 'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js', // 'https://cdn.bootcss.com/axios/0.19.2/axios.min.js' // ] } module.exports = { // pluginOptions: { // 'style-resources-loader': { // preProcessor: 'less', // // patterns: [path.resolve(__dirname, './src/assets/style/shopmall/shopmall.public.less')] // patterns: [path.resolve(__dirname, './src/assets/style/common/public.less')] // } // }, pluginOptions: { 'style-resources-loader': { preProcessor: 'less', patterns: [path.resolve(__dirname, './src/assets/style/common/public.less')] } }, transpileDependencies: ['sockjs-client', 'js-base64', 'js-cookie', 'element-china-area-data'], // 是否引用第三方 es6+ 的插件进行ie兼容 css: { // 是否使用css分离插件 ExtractTextPlugin extract: false, // 开启 CSS source maps? sourceMap: false, // css预设器配置项 loaderOptions: {}, // 启用 CSS modules for all css / pre-processor files. modules: false }, chainWebpack: (config) => { config.plugins.delete('prefetch') // ============注入cdn start============ config.plugin('html').tap(args => { // 生产环境或本地需要cdn时,才注入cdn if (isProduction || devNeedCdn) args[0].cdn = cdn return args }) // ============注入cdn start============ // ============设置的别名 start============ config.resolve.alias .set('@', resolve('src')) .set('@api', resolve('src/api')) .set('@assets', resolve('src/assets')) .set('@comp', resolve('src/components')) .set('@views', resolve('src/views')) // ============设置的别名 end============ // webpack 会默认给commonChunk打进chunk-vendors,所以需要对webpack的配置进行delete config.optimization.delete('splitChunks') if (process.env.npm_config_report) { config .plugin('webpack-bundle-analyzer') .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin) .end() } }, configureWebpack: (config) => { // 设置版本号-添加时间戳(解决浏览器缓存问题,启用协商缓存模式) const Timestamp = new Date().getTime() // 输出重构【模块名称.hash值.时间戳】 config.output.filename = `[name].[hash].${Timestamp}.js` config.output.chunkFilename = `[name].[hash].${Timestamp}.js` // 用cdn方式引入,则构建时要忽略相关资源 if (isProduction || devNeedCdn) config.externals = cdn.externals // 公共代码抽离 // 生产环境相关配置 if (isProduction) { // gzip压缩 const productionGzipExtensions = ['html', 'js', 'css'] config.plugins.push( new CompressionWebpackPlugin({ filename: '[path].gz[query]', algorithm: 'gzip', test: new RegExp( '\\.(' + productionGzipExtensions.join('|') + ')$' ), threshold: 1000, // 只有大小大于该值的资源会被处理 10k minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理 deleteOriginalAssets: false // 删除原文件 }) ) // 用于根据模块的相对路径生成 hash 作为模块 id, 一般用于生产环境 config.plugins.push( new HashedModuleIdsPlugin() ) // 公共代码抽离 config.optimization = { runtimeChunk: 'single', splitChunks: { chunks: 'all', maxInitialRequests: Infinity, minSize: 1000 * 60, cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name(module) { // 排除node_modules 然后吧 @ 替换为空 ,考虑到服务器的兼容 const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1] return `npm.${packageName.replace('@', '')}` } } } } } // 取消webpack警告的性能提示 config.performance = { hints: 'warning', // 入口起点的最大体积 maxEntrypointSize: 1000 * 500, // 生成文件的最大体积 maxAssetSize: 1000 * 1000, // 只给出 js 文件的性能提示 assetFilter: function(assetFilename) { return assetFilename.endsWith('.js') } } } }, devServer: { disableHostCheck: true, overlay: { warnings: false, errors: false }, port: '8082', open: true, // 自动启动浏览器 proxy: { '/bidprocurement': { // target: 'https://www.nengcb.com/bidprocurement/', // 正式 // target: 'http://192.168.1.55:8760/bidprocurement', // 刘纯本机 // target: 'http://192.168.1.239/bidprocurement', // 刘纯本地 // target: 'http://192.168.1.39:8760/service-app/', // 龚涛本地 target: 'http://47.94.166.241:8760/service-app/', // 龚涛本地 ws: true, changeOrigin: true, pathRewrite: { '^/bidprocurement': '/' } }, '/service-app': { // target: 'https://www.nengcb.com/bidprocurement/', // 正式 // target: 'http://192.168.1.55:8760/bidprocurement', // 刘纯本机 // target: 'http://192.168.1.239/bidprocurement', // 刘纯本地 // target: 'http://192.168.1.39:8760/service-app/', // 龚涛本地 target: 'http://47.94.166.241:8760/service-app/', // 龚涛本地 ws: true, changeOrigin: true, pathRewrite: { '^/service-app': '/' } } } }, productionSourceMap: false, lintOnSave: !isProduction, publicPath: publicPath() }