vue2-webpack5-pack
Version:
开箱即用的 vue2 + Webpack5 项目模板
194 lines (193 loc) • 6.21 kB
JavaScript
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require("terser-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const webpack = require("webpack");
const { VueLoaderPlugin } = require('vue-loader');
const chalk = require('chalk');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const { rootResolve, devMode } = require('./utils.js');
module.exports = {
resolve: {
extensions: [".js", ".jsx", ".json", ".vue"], // 可省略后缀
alias: {
'@': rootResolve('src')
}
},
entry: {
main: rootResolve('src/main.js')
},
output: {
filename: 'js/[name].[chunkhash].js',
path: rootResolve('dist'),
clean: true,
publicPath: devMode ? '/' : './', // 生产环境上根据不同场景可能改变根路径,如 "./h5/"
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
compiler: require('vue-template-compiler'), // 默认编译器
compilerOptions: { // 编译器选项
preserveWhitespace: false // 移除模板标签之间的换行空格
}
}
},
{
test: /\.less$/i,
use: [
// 'style-loader',
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
}
},
'css-loader',
'postcss-loader',
'less-loader',
],
},
{
test: /\.css$/i,
use: [
// 'style-loader', // 将 CSS 生成 style 标签插入 HTML 中
{
loader: MiniCssExtractPlugin.loader, //抽离css的loader
options: {
publicPath: '../', // css抽离后路径发生变化
}
},
'css-loader',
'postcss-loader'
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
generator:{
filename: 'images/[name].[contenthash][ext]'
},
parser:{
dataUrlCondition: {
maxSize: 20*1024 // 操过20kb就使用图片资源,小于20kb就使用base64编码
}
}
},
// 打包字体图标
{
test: /\.(eot|svg|woff|woff2|ttf)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[contenthash][ext]',
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
title: 'template',
template: rootResolve("public/index.html"),
inject: 'body',
filename: 'index.html',
chunks: ['main'],
minify: {
removeComments: true, // 移除html中的注释
removeAttributeQuotes: true, // 移除属性中的双引号
collapseWhitespace: true, // 去除空格与换行
}
}),
new MiniCssExtractPlugin({
filename: devMode ? 'style/[name].css' : 'style/[name].[contenthash].css',
chunkFilename: devMode ? "style/[id].css" : "style/[id].[contenthash].css",
ignoreOrder: false,
}),
new CopyWebpackPlugin({
patterns: [
{
from: rootResolve('public'),
to: rootResolve('dist'),
globOptions: {
ignore: ['**/*.html'] // 忽略不需要复制的文件
}
},
],
}),
// 设定环境变量
new webpack.DefinePlugin({
"PUBLIC_PATH": JSON.stringify("./"),
"process.env": JSON.stringify({ // 传递的值必须字符串化
// ...process.env,
"SHOW_CONFIG_HEADER": "TRUE"
})
}),
new VueLoaderPlugin(),
// 编译进度提示
new ProgressBarPlugin({
format: `:msg [:bar] ${chalk.green.bold(':percent')} (:elapsed s)`,
clear: false
}),
],
optimization: {
// usedExports: true, // tree sharking,与 package.json 的 sideEffects 配合使用
minimize: true,
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin({
extractComments: false, // 不创建许可证文件和注释 vendors.js.LICENSE.txt
terserOptions: {
format: {
comments: false, // 删除js中的注释
},
compress: {
// 移除所有console相关代码;
drop_console: true,
// 移除自动断点功能;
drop_debugger: true,
// 配置移除指定的指令,如console.log,alert
pure_funcs: ['console.log', 'console.error'],
},
}
})
],
splitChunks: {
// 实际拆分条件优先级: maxSize < minSize
minSize: 20*1024, // 限制拆分包的最小值,达到这个值,才能够拆出新包
maxSize: 50*1024, // 单位:字节 约等于40kb,生成的块大于40KB的chunk将拆分成较小部分,增加请求数量以实现更好的缓存
minChunks: 1, // 引入次数大于等于该值时,才会进行分包
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
moduleIds: 'deterministic',
},
performance: {
hints: devMode ? false : 'warning',
// 入口起点的最大体积 整数类型(以字节为单位)
maxEntrypointSize: 2000000, // 1kb=1024个字节=8比特
// 生成文件的最大体积 整数类型(以字节为单位 300k)
maxAssetSize: 1000000,
// 只给出 js/css 文件的性能提示
assetFilter: function(assetFilename) {
return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
}
},
// 外部扩展引入,防止单个文件体积过大,影响首屏渲染
externals: {
"vue": 'Vue',
"vuex": "Vuex",
"axios": 'axios',
},
};