const CompressionWebpackPlugin = require('compression-webpack-plugin') // 导入compression-webpack-plugin插件 const VueFilenameInjector = require('@d2-projects/vue-filename-injector') // 导入@d2-projects/vue-filename-injector插件 const ThemeColorReplacer = require('webpack-theme-color-replacer') // 导入webpack-theme-color-replacer插件 const forElementUI = require('webpack-theme-color-replacer/forElementUI') // 导入forElementUI模块 const { set, each, compact, map, keys } = require('lodash') // 导入lodash工具库中的一些方法 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const resolve = dir => require('path').join(__dirname, dir) // 定义一个辅助函数,用于解析路径 // 添加环境变量 process.env.VUE_APP_VERSION = require('./package.json').version // 将package.json中的版本号作为环境变量VUE_APP_VERSION的值 process.env.VUE_APP_BUILD_TIME = require('dayjs')().format('YYYY-M-D HH:mm:ss') // 将当前时间作为构建时间的环境变量VUE_APP_BUILD_TIME的值 // 多页面的构建配置 const pages = { index: { entry: 'src/main.js', // 入口文件 template: 'public/index.html', // HTML模板文件 filename: 'index.html', // 构建后的文件名 chunks: [ 'manifest', 'index', 'chunk-index', 'chunk-vendor', 'chunk-common', 'chunk-vue', 'chunk-element' ] // 引入的代码块名称 }, } // 设置以CDN形式引入的外部依赖包 const cdn = { // Which external dependencies related to index page are introduced in the form of CDN links index: [ // { // name: 'axios', // library: 'axios', // js: 'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js', // css: '' // } ], } // 设置不参与构建的外部依赖包 const externals = {} keys(pages).forEach(name => { cdn[name].forEach(p => { externals[p.name] = p.library }) }) module.exports = { // 公共路径 publicPath: process.env.VUE_APP_PUBLIC_PATH || '/', // 禁用ESLint检查 lintOnSave: false, devServer: { publicPath: process.env.VUE_APP_PUBLIC_PATH || '/', disableHostCheck: process.env.NODE_ENV === 'development' }, css: { loaderOptions: { sass: { additionalData: '@use "@/assets/style/public.scss" as *;' }, less: { lessOptions: { modifyVars: { blue: '#2262AB' } } } } }, pages, // 多页面的配置选项 configureWebpack: config => { const configNew = {} if (process.env.NODE_ENV === 'production') { configNew.externals = externals // 将之前定义的externals配置应用到新的Webpack配置中 configNew.plugins = [ // 这个插件会创建一个可视化的树状图,显示你的 bundle 中各个模块的大小。 new BundleAnalyzerPlugin({ analyzerMode: 'static' }), // gzip压缩 new CompressionWebpackPlugin({ filename: '[path].gz[query]', // 压缩文件的命名格式 test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'), // 正则表达式,用于匹配需要进行压缩的文件类型 threshold: 10240, // 仅对超过10KB的文件进行压缩 minRatio: 0.8, // 仅对压缩比例达到0.8以上的文件进行压缩 deleteOriginalAssets: false // 是否删除原始文件,默认为false,即保留原始文件 }) ] } return configNew }, // default: https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-service/lib/config/base.js chainWebpack: config => { config.optimization.runtimeChunk({ name: 'manifest' }) config.optimization.splitChunks({ cacheGroups: { // 所有页面共享的外部依赖 libs: { name: 'chunk-vendor', chunks: 'initial', minChunks: 1, test: /[\\/]node_modules[\\/]/, priority: 1, reuseExistingChunk: true, enforce: true }, // 所有页面共享的代码 common: { name: 'chunk-common', chunks: 'initial', minChunks: 2, maxInitialRequests: 5, minSize: 0, priority: 2, reuseExistingChunk: true, enforce: true }, // 仅在index页面中使用的外部依赖 index: { name: 'chunk-index', chunks: 'all', minChunks: 1, test: /[\\/]node_modules[\\/](sortablejs|screenfull|nprogress|hotkeys-js|fuse\.js|better-scroll|lowdb|shortid)[\\/]/, priority: 3, reuseExistingChunk: true, enforce: true }, // 仅在mobile页面中使用的外部依赖 mobile: { name: 'chunk-mobile', chunks: 'all', minChunks: 1, test: /[\\/]node_modules[\\/](vant)[\\/]/, priority: 3, reuseExistingChunk: true, enforce: true }, // Vue家族的包 vue: { name: 'chunk-vue', test: /[\\/]node_modules[\\/](vue|vue-router|vuex)[\\/]/, chunks: 'all', priority: 3, reuseExistingChunk: true, enforce: true }, // 仅包含element-ui element: { name: 'chunk-element', test: /[\\/]node_modules[\\/]element-ui[\\/]/, chunks: 'all', priority: 3, reuseExistingChunk: true, enforce: true } } }) // 将CDN设置添加到html-webpack-plugin插件的选项中 keys(pages).forEach(name => { const packages = cdn[name] config.plugin(`html-${name}`).tap(options => { const setting = { css: compact(map(packages, 'css')), js: compact(map(packages, 'js')) } set(options, '[0].cdn', process.env.NODE_ENV === 'production' ? setting : []) return options }) }) // 移除懒加载模块的预取和预加载设置 each(keys(pages), name => { config.plugins.delete(`prefetch-${name}`) config.plugins.delete(`preload-${name}`) }) // webpack-theme-color-replacer插件 // config // .plugin('theme-color-replacer') // .use(ThemeColorReplacer, [{ // fileName: 'css/theme-colors.[contenthash:8].css', // matchColors: [ // ...forElementUI.getElementUISeries(process.env.VUE_APP_ELEMENT_COLOR) // Element-ui主色系列 // ], // 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. // changeSelector: forElementUI.changeSelector // }]) config // 开发环境下,不包含列信息的sourcemap .when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map') ) // 添加文件名 .when( process.env.VUE_APP_SCOURCE_LINK === 'TRUE', config => VueFilenameInjector(config, { propName: process.env.VUE_APP_SOURCE_VIEWER_PROP_NAME }) ) // markdown config.module .rule('md') .test(/\.md$/) .use('text-loader') .loader('text-loader') .end() // svg const svgRule = config.module.rule('svg') svgRule.uses.clear() svgRule .include .add(resolve('src/assets/svg-icons/icons')) .end() .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'd2-[name]' }) .end() // 图片排除 const imagesRule = config.module.rule('images') imagesRule .test(/\.(png|jpe?g|gif|webp|svg)(\?.*)?$/) .exclude .add(resolve('src/assets/svg-icons/icons')) .end() }, productionSourceMap: false, // 生产环境禁用SourceMap pluginOptions: { i18n: { locale: 'zh-chs', // 默认语言环境为中文简体 fallbackLocale: 'en', // 回退语言环境为英文 localeDir: 'locales', // 语言包存放的目录 enableInSFC: true // 在单文件组件中启用i18n } } }