// vue.config.js
const path = require("path");
function resolve(dir) {
console.log(path);
//path大对象,里面有很多方法
console.log(dir);
//src/components/icon/svg
console.log(path.join(__dirname, dir));
//C:\Users\yang\Desktop\WORK\CePing-dl\src\components\icon\svg
return path.join(__dirname, dir);
}
module.exports = {
publicPath: "/",
// 将构建好的文件输出到哪里
outputDir: "dist",
// 放置生成的静态资源(js、css、img、fonts)的目录。
assetsDir: "static",
// 指定生成的 index.html 的输出路径
indexPath: "index.html",
// 是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。
runtimeCompiler: false,
// 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来。
transpileDependencies: [],
// 生产环境关闭 source map
productionSourceMap: false,
//设置为 true 或 'warning' 时,eslint-loader 会将 lint 错误输出为编译警告。默认情况下,警告仅仅会被输出到命令行,且不会使得编译失败。
// lintOnSave: true,
// 配置css
css: {
// 是否使用css分离插件 ExtractTextPlugin
extract: true,
sourceMap: true,
// css预设器配置项,移动端常用
loaderOptions: {
postcss: {
plugins: [
require("postcss-px2rem")({
remUnit: 100
})
]
}
},
// 启用 CSS modules for all css / pre-processor files.
modules: false
},
// 是一个函数,会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。
//函数写法
chainWebpack: config => {
// 配置别名
config.resolve.alias
.set("@", resolve("src"))
.set("assets", resolve("src/assets"))
.set("components", resolve("src/components"))
.set("views", resolve("src/views"));
config.optimization.minimizer("terser").tap(args => {
// 去除生产环境console
args[0].terserOptions.compress.drop_console = true;
return args;
});
const svgRule = config.module.rule("svg");
svgRule.uses.clear();
svgRule.exclude.add(/node_modules/);
svgRule
.test(/\.svg$/)
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({
symbolId: "icon-[name]"
});
const imagesRule = config.module.rule("images");
imagesRule.exclude.add(resolve("src/components/icon/svg"));
config.module.rule("images").test(/\.(png|jpe?g|gif|svg)(\?.*)?$/);
},
//对象的配置的写法(和函数写法二选一)
// configureWebpack: {
// resolve: {
// alias: {
// "@": resolve("src"),
// 'assets': resolve('src/assets')
// }
// }
// }
configureWebpack: config => {
/*有插件就在这里配置
config.plugins.push(xxx);
if (process.env.NODE_ENV === "production") {
config.plugins.push(xxx);
}
*/
//这里可以修改打包提示文件过大的配置
// if (process.env.NODE_ENV === "production") {
// // 为生产环境修改配置...
// config.mode = "production";
// config["performance"] = {
// //打包文件大小配置
// maxEntrypointSize: 10000000,
// maxAssetSize: 30000000,
// };
// }
},
performance: { hints: false }, //关闭打包提示文件过大的警告
// 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
parallel: require("os").cpus().length > 1,
devServer: {
host: "0.0.0.0",
port: 8088, // 端口号
https: false, // https:{type:Boolean}
open: false, // 配置自动启动浏览器 open: 'Google Chrome'-默认启动谷歌
// 配置多个代理
proxy: {
"/api": {
target: "http://xxx",
// ws: true, // 代理的WebSockets
changeOrigin: true, // 允许websockets跨域
pathRewrite: {
"^/api": "/api"
}
},
"/api2": {
target: "http://xxx/",
// ws: true, // 代理的WebSockets
changeOrigin: true, // 允许websockets跨域
pathRewrite: {
"^/api2": "/api"
}
},
"/api3": {
target: "http://dceccn.com:8888/",
// ws: true, // 代理的WebSockets
changeOrigin: true, // 允许websockets跨域
pathRewrite: {
"^/api3": "/api"
}
}
}
}
};
全面配置
图片压缩
cnpm install --save-dev image-webpack-loader
module.exports = {
// 根据你的实际情况更改这里
publicPath,
assetsDir: 'assets',
lintOnSave: true,
// image 压缩 定义在 chainWebpack 中
chainWebpack: config => {
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
bypassOnDebug: true
})
.end()}
}
公共代码抽离
从 webpack4 开始官方移除了 commonchunk 插件,改用了 optimization 属性进行更加灵活的配置,这也应该是从 V3 升级到 V4 的代码修改过程中最为复杂的一部分
splitChunks: {
chunks: "async”,//默认作用于异步 chunk,值为 all/initial/async/function(chunk),值为 function 时第一个参数为遍历所有入口 chunk 时的 chunk 模块,chunk._modules 为 chunk 所有依赖的模块,通过 chunk 的名字和所有依赖模块的 resource 可以自由配置,会抽取所有满足条件 chunk 的公有模块,以及模块的所有依赖模块,包括 css
minSize: 30000, //表示在压缩前的最小模块大小,默认值是 30kb
minChunks: 1, // 表示被引用次数,默认为 1;
maxAsyncRequests: 5, //所有异步请求不得超过 5 个
maxInitialRequests: 3, //初始话并行请求不得超过 3 个
automaticNameDelimiter:'~',//名称分隔符,默认是~
name: true, //打包后的名称,默认是 chunk 的名字通过分隔符(默认是~)分隔
cacheGroups: { //设置缓存组用来抽取满足不同规则的 chunk,下面以生成 common 为例
common: {
name: 'common', //抽取的 chunk 的名字
chunks(chunk) { //同外层的参数配置,覆盖外层的 chunks,以 chunk 为维度进行抽取
},
test(module, chunks) { //可以为字符串,正则表达式,函数,以 module 为维度进行抽取,只要是满足条件的 module 都会被抽取到该 common 的 chunk 中,为函数时第一个参数是遍历到的每一个模块,第二个参数是每一个引用到该模块的 chunks 数组。自己尝试过程中发现不能提取出 css,待进一步验证。
},
priority: 10, //优先级,一个 chunk 很可能满足多个缓存组,会被抽取到优先级高的缓存组中
minChunks: 2, //最少被几个 chunk 引用
reuseExistingChunk: true,// 如果该 chunk 中引用了已经被抽取的 chunk,直接引用该 chunk,不会重复打包代码
enforce: true // 如果 cacheGroup 中没有设置 minSize,则据此判断是否使用上层的 minSize,true:则使用 0,false:使用上层 minSize
}
}
}
第三方模块抽离
// 公共代码抽离
configureWebpack: config => {
//....
//优化项配置
config.optimization = {
splitChunks: { // 分割代码块
cacheGroups: {
vendor: {//第三方库抽离
chunks: 'all',
test: /node_modules/,
name: 'vendor',
minChunks: 1,//在分割之前,这个代码块最小应该被引用的次数
maxInitialRequests: 5,
minSize: 0,//大于 0 个字节
priority: 100//权重
},
common: { //公用模块抽离
chunks: 'all',
test: /[\\/]src[\\/]js[\\/]/,
name: 'common',
minChunks: 2,在分割之前,这个代码块最小应该被引用的次数
maxInitialRequests: 5,
minSize: 0,//大于 0 个字节
priority: 60
},
styles: { //样式抽离
name: 'styles',
test: /\.(sa|sc|c)ss$/,
chunks: 'all',
enforce: true
},
runtimeChunk: {
name: 'manifest'
}
}
}
}
}
完整配置
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 去掉注释
const CompressionWebpackPlugin = require('compression-webpack-plugin'); // 开启压缩
const { HashedModuleIdsPlugin } = require('webpack');
function resolve(dir) {
return path.join(__dirname, dir)
}
const isProduction = process.env.NODE_ENV === 'production';
// cdn 预加载使用
const externals = {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios',
"element-ui": "ELEMENT"
}
const cdn = {
// 开发环境
dev: {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
],
js: []
},
// 生产环境
build: {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
],
js: [
'https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js',
'https://cdn.jsdelivr.net/npm/vue-router@3.0.1/dist/vue-router.min.js',
'https://cdn.jsdelivr.net/npm/vuex@3.0.1/dist/vuex.min.js',
'https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js',
'https://unpkg.com/element-ui/lib/index.js'
]
}
}
module.exports = {
lintOnSave: false, // 关闭 eslint
productionSourceMap: false,
publicPath: './',
outputDir: process.env.outputDir, // 生成文件的目录名称
chainWebpack: config => {
config.resolve.alias
.set('@', resolve('src'))
// 压缩图片
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({ bypassOnDebug: true })
// webpack 会默认给 commonChunk 打进 chunk-vendors,所以需要对 webpack 的配置进行 delete
config.optimization.delete('splitChunks')
config.plugin('html').tap(args => {
if (process.env.NODE_ENV === 'production') {
args[0].cdn = cdn.build
}
if (process.env.NODE_ENV === 'development') {
args[0].cdn = cdn.dev
}
return args
})
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
},
configureWebpack: config => {
const plugins = [];
if (isProduction) {
plugins.push(
new UglifyJsPlugin({
uglifyOptions: {
output: {
comments: false, // 去掉注释
},
warnings: false,
compress: {
drop_console: true,
drop_debugger: false,
pure_funcs: ['console.log']//移除 console
}
}
})
)
// 服务器也要相应开启 gzip
plugins.push(
new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.(js|css)$/,// 匹配文件名
threshold: 10000, // 对超过 10k 的数据压缩
deleteOriginalAssets: false, // 不删除源文件
minRatio: 0.8 // 压缩比
})
)
// 用于根据模块的相对路径生成 hash 作为模块 id, 一般用于生产环境
plugins.push(
new HashedModuleIdsPlugin()
)
// 开启分离 js
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');
}
}
// 打包时 npm 包转 CDN
config.externals = externals;
}
return { plugins }
},
pluginOptions: {
// 配置全局 less
'style-resources-loader': {
preProcessor: 'less',
patterns: [resolve('./src/style/theme.less')]
}
},
devServer: {
open: false, // 自动启动浏览器
host: '0.0.0.0', // localhost
port: 6060, // 端口号
https: false,
hotOnly: false, // 热更新
proxy: {
'^/sso': {
target: process.env.VUE_APP_SSO, // 重写路径
ws: true, //开启 WebSocket
secure: false, // 如果是 https 接口,需要配置这个参数
changeOrigin: true
}
}
}
}