const { resolve } = require("path");
const hardPlugin = require("hard-source-webpack-plugin") // 使用缓存,优化启动速度
// const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer") // 打包分析插件
const CompressionPlugin = require("compression-webpack-plugin"); // 开启gzip压缩, 按需引用
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') // js压缩,附带去除console,貌似说不支持es6,被terser替代,目前没发现毛病
const prod = process.env.NODE_ENV === 'production' // 判断是否是生产环境
function setLess(config,types) {
types.forEach(type => {
let rule = config.module.rule('less').oneOf(type)
rule.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [resolve(__dirname, './src/assets/less/common.less')]
});
});
}
module.exports = {
publicPath: './',
productionSourceMap: false, // 生产环境是否要生成 sourceMap
outputDir: 'dist', // 打包生成的包名
assetsDir: 'assets', // 放置静态文件夹目录
// configureWebpack有两种写法,一种是对象的写法,还有一种是函数的写法
// configureWebpack对象写法
// configureWebpack: {
// plugins: [
// new hardPlugin({
// cacheDirectory: resolve(__dirname, "cache")
// }),
// // new BundleAnalyzerPlugin() // 模块打包分析插件
// ]
// },
// configureWebpack函数写法
configureWebpack: config => {
const plugins = [];
plugins.push(
new hardPlugin({
cacheDirectory: resolve(__dirname, "cache")
}),
// new BundleAnalyzerPlugin() // 模块打包分析插件
new UglifyJsPlugin({
uglifyOptions: {
compress: {
// warnings: false,
drop_debugger: true, // console
drop_console: true,
pure_funcs:['console.log'] // 移除console
},
},
sourceMap: false,
parallel: true,
})
)
config.plugins = [...config.plugins, ...plugins];
},
chainWebpack: config => {
const types = ['vue-modules', 'vue', 'normal-modules', 'normal'];
setLess(config,types);
config.resolve.alias // 设置别名
.set('@', resolve('src'))
if(prod) {
config.module.rule('images').use('url-loader') // 图片转为base64,不用手动下载url-loader的
.tap(options => ({
name: './assets/images/[name].[contenthash:6].[ext]',
quality: 85,
limit: 10*1024, // 小于10kb的转为base64
esModule: false,
}));
// js文件output输出配置
config.output.filename('./js/[name].[chunkhash:6].js');
config.output.chunkFilename('./js/[name].[chunkhash:6].js');
// css合并 相当于webapck中的 mini-css-extract-plugin,可写可不写,@vue/cli已经默认打包到合并到css文件
config.plugin('extract-css').tap(args => [{
filename: 'css/[name].[contenthash:6].css',
chunkFilename: 'css/[name].[contenthash:6].css'
}]);
// js压缩插件 相当于webpack中的terser-webpack-plugin,不需要手动下载
// config.optimization.minimize(true)
// .minimizer('terser')
// .tap(args => {
// let { terserOptions } = args[0];
// terserOptions.compress.drop_console = true;
// terserOptions.compress.drop_debugger = true;
// return args
// });
// js gzip压缩
// config.plugin("compression").use(CompressionPlugin, [
// {
// test: /\.(js|css)?$/i, // 哪些文件要压缩
// filename: "[path].gz[query]", // 压缩后的文件名
// algorithm: "gzip", // 使用gzip压缩
// minRatio: 0.8, // 压缩率小于0.8才会压缩
// deleteOriginalAssets: false, // 删除未压缩的文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false
// },
// ]);
// 排除npm包
config.externals({
vue: "Vue",
"vue-router": "VueRouter",
vuex: "Vuex",
// "element-ui": 'element-ui'
});
}
},
devServer: {
port: '9527', // 开发时运行的端口
host: 'localhost', // 开发运行时域名
open: true, // 是否自动打开浏览器
proxy: { // 处理跨域
"/api": {
target: 'http://localhost:5000', // target代理到后端接口: http://localhost:5000
changeOrigin: true,
pathRewrite: { // 路径重写
"^/api": ''
}
}
}
}
}