Terser
对代码进行压缩、丑化
const TerserPlugin = require("terser-webpack-plugin");
optimization: {
minimize: true, //在开发环境下启用 CSS 优化
minimizer: [
new TerserPlugin({
extractComments: false,
terserOptions: {
compress: {
arguments: true,// 将函数中使用的argumens[index]转换成对应的形参名称
unused: false,
},
mangle: true,
keep_fnames: true,
},
}),
],
}
compress中的属性:
arrows: class 或者object中的函数,转换成箭头函数
arguments:将函数中使用的argumens[index]转换成对应的形参名称
dead_code:移除不可达的代码
mangle中的属性:
toplevel:默认是false,顶层作用域中的变量名称进行丑化
keep_classnames 默认是false,是否保持依赖的类的名称
keep_fnames:默认是false,是否保持原来的函数名称
css压缩
npm i css-minimizer-webpack-plugin -D
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
optimization: {
new CssMinimizerPlugin({
parallel: true,
}),
}
代码拆分
脚本命令运行时可以携带参数
"scripts": {
"build": "npx webpack --config ./config/com.config.js --env production",
"server": "npx webpack server --config ./config/com.config.js --env development",
"ts-check": "tsc --noEmit",
"tc-check-watch": "tec --noEmit --watch"
},
module.exports可以导出一个函数,这个函数可以接受环境变量env
const commonConfig ={}
// webpack允许导出一个函数
module.exports = function (env) {
console.log(env);
return commonConfig;
};
安装merge
npm i webpack-merge -D
com.config.js存放开发和生产环境都会用到的配置
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const { DefinePlugin } = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const { merge } = require("webpack-merge");
const devConfig = require("./dev.config");
const prodConfig = require("./prod.config");
const config = function (isProduct) {
return {
entry: {
main: {
import: "./src/main.js",
dependOn: "shared",
},
index: {
import: "./src/index.js",
dependOn: "shared",
},
shared: "dayjs",
},
output: {
filename: "[name]-bundle.js",
path: path.resolve(__dirname, "../build"),
clean: true,
chunkFilename: "[name]-chunk.js", //对分包的文件命名
},
resolve: {
extensions: [".js", ".json", ".jsx", ".tsx", ".ts"],
alias: {
"@": path.resolve(__dirname, "../src"),
},
},
module: {
rules: [
{
test: /\.css$/,
use: [
isProduct ? MiniCssExtractPlugin.loader : "style-loader",
//"style-loader", 开发
// MiniCssExtractPlugin.loader,//生产
"css-loader",
"postcss-loader",
],
},
{
test: /\.scss$/,
use: [
isProduct ? MiniCssExtractPlugin.loader : "style-loader",
"css-loader",
"sass-loader",
],
},
{
test: /\.(png|jpe?g|gif|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024,
},
},
generator: {
filename: "img/[hash][ext]",
},
},
{
test: /\.jsx$/,
use: "babel-loader",
},
{
test: /\.ts$/,
use: "babel-loader",
},
{
test: /\.m?js$/,
exclude: /node_modules/, //排除/node_modules/ 下的文件
use: {
loader: "babel-loader",
},
},
{
test: /\.ts$/,
use: "babel-loader",
},
],
},
plugins: [
// new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "webpack项目",
template: "./src/index.html",
}),
new DefinePlugin({
BASE_URL: "'./public'",
}),
],
};
};
module.exports = function (env) {
const isProduct = env.production;
let mergeConfig = isProduct ? prodConfig : devConfig;
return merge(config(isProduct), mergeConfig);
};
dev.config.js 开发环境的配置
const path = require("path");
module.exports = {
mode: "development",
devServer: {
hot: true,
open: true,
port: "7070",
host: "127.0.0.1",
compress: true,
static: [
//静态目录
{
directory: path.join(__dirname, "public"),
},
{
directory: path.join(__dirname, "content"),
},
],
proxy: [
{
context: ["/api"],
target: "http://localhost:3000",
pathRewrite: { "^/api": "" },
},
],
},
performance: {
//配置如何展示性能提示 例如,如果一个资源超过 250kb,webpack 会对此输出一个警告来通知你。
maxEntrypointSize: 50000000,
maxAssetSize: 30000000,
},
};
prod.config.js 生产环境的配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
mode: "production",
plugins: [
// new CleanWebpackPlugin(),
new CopyPlugin({
//把public下的文件拷贝到build下的public下
patterns: [{ from: "public", to: "public" }],
}),
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[name]_chunk.css",
}),
],
optimization: {
chunkIds: "deterministic", //选择模块 id 时需要使用哪种算法
usedExports: true, //去决定每个模块的到处内容是否被使用 ,生产环境下默认开启,与minimizer配合使用可以去除定义后没有使用的代码
runtimeChunk: {
name: "runtime", //运行时代码提取到单独的文件中的方式。这有助于避免在每个模块更改时导致运行时代码的变化,从而减少主要包的大小并提高缓存利用率。
},
//分包
splitChunks: {
chunks: "all",
//
maxSize: 20000,
//将包拆成不小于minSize的包,如果打不到minSize,那么这个包就不会拆分(会被合并到其他包中)
minSize: 10000,
cacheGroups: {
venders: {
//匹配/node_modules/下的包 [\\/] /node_modules和\node_modules 为了处理不同系统的问题
// \\ 第一个\是为了转意,有些字符有特殊含义
test: /[\\/]node_modules[\\/]/,
filename: "[id]_[contenthash:6]_vender.js",
},
foo: {
test: /utils/,
filename: "[id]_[contenthahs:6]_utils.js",
},
},
},
minimize: true, //在开发环境下启用 CSS 优化
//代码丑化设置
minimizer: [
new TerserPlugin({
extractComments: false,
terserOptions: {
compress: {
arguments: true,
unused: false,
},
mangle: true,
keep_fnames: true,
},
}),
new CssMinimizerPlugin({
parallel: true,
}),
],
},
};
usedExports ,对js进行tree shinking
对代码中没有用到的代码做标记,配合Terser使用可以删除代码中没有用到的代码。
optimization: {
chunkIds: "deterministic", //选择模块 id 时需要使用哪种算法
usedExports: true, //去决定每个模块的到处内容是否被使用 ,生产环境下默认开启,与minimizer配合使用可以去除定义后没有使用的代码
runtimeChunk: {
name: "runtime", //运行时代码提取到单独的文件中的方式。这有助于避免在每个模块更改时导致运行时代码的变化,从而减少主要包的大小并提高缓存利用率。
},
//分包
splitChunks: {
chunks: "all",
//
maxSize: 20000,
//将包拆成不小于minSize的包,如果打不到minSize,那么这个包就不会拆分(会被合并到其他包中)
minSize: 10000,
cacheGroups: {
venders: {
//匹配/node_modules/下的包 [\\/] /node_modules和\node_modules 为了处理不同系统的问题
// \\ 第一个\是为了转意,有些字符有特殊含义
test: /[\\/]node_modules[\\/]/,
filename: "[id]_[contenthash:6]_vender.js",
},
foo: {
test: /utils/,
filename: "[id]_[contenthahs:6]_utils.js",
},
},
},
minimize: true, //在开发环境下启用 CSS 优化
//代码丑化设置
minimizer: [
new TerserPlugin({
extractComments: false,
terserOptions: {
compress: {
arguments: true,
unused: false,
},
mangle: true,
keep_fnames: true,
},
}),
new CssMinimizerPlugin({
parallel: true,
}),
],
},
对css进行tree shaking
npm i purgecss-webpack-plugin -D
npm i glob -D Node没有内置
没有用到的css文件不会被打包
const { PurgeCSSPlugin } = require("purgecss-webpack-plugin");
const path = require("path");
const glob = require("glob");
plugins: [
// new CleanWebpackPlugin(),
new CopyPlugin({
//把public下的文件拷贝到build下的public下
patterns: [{ from: "public", to: "public" }],
}),
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[name]_chunk.css",
}),
new PurgeCSSPlugin({
paths: glob.sync(`${path.resolve(__dirname, "../src")}/**/*`, {
nodir: true,
}), //src/xx/x nodir:true,不是查找文件夹,而是文件
safelist: function () {
return {
standard: ["aa",], //白名单
// deep: [/^safelisted-deep-/],
// greedy: [/^safelisted-greedy/],
};
},
}),
],
PurgeCSSPlugin可以设置白名单 safelist,设置后无论使用还是没有使用都会被打包
new PurgeCSSPlugin({
paths: glob.sync(`${path.resolve(__dirname, "../src")}/**/*`, {
nodir: true,
}), //src/xx/x nodir:true,不是查找文件夹,而是文件
safelist: function () {
return {
standard: ["aa",], //白名单
// deep: [/^safelisted-deep-/],
// greedy: [/^safelisted-greedy/],
};
},
}),
import(“…/css/index.css”):这种方式使用了动态import,在运行时会动态地加载模块。
import"…/css/index.css":这种方式是标准的静态import,在编译时会静态地确定模块的依赖关系。
MiniCssExtractPlugin的chunkFilename可以给异步导入的包命名
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[name]_chunk.css",//异步导入的分包的css的名字
ignoreOrder: true, // 忽略 CSS 中的顺序问题
}),
Scope Hoisting
对作用域进行提升,使打包后的代码更小,运行更快。
Scope Hoisting可以将函数合并到一个模块中来运行。
生产环境下默认会开启,开发环境下需要手动打开。
plugins: [
// new CleanWebpackPlugin(),
new CopyPlugin({
//把public下的文件拷贝到build下的public下
patterns: [{ from: "public", to: "public" }],
}),
new webpack.optimize.ModuleConcatenationPlugin(),
],
HTTP压缩
HTTP压缩是一种在传输过程中对HTTP,请求和响应数据进行压缩的技术,可以显著减小数据传输量,从而加快网页的加载速度,减少网络传输所消耗的带宽。
常用的HTTP压缩算法包括Gzip和Deflate。这些算法会压缩文本、脚本、样式表和其他支持压缩的文件格式,使它们在服务器端进行压缩后再在客户端进行解压缩,以加快数据传输速度。
HTTP压缩的流程:
- http的数据在服务器发送前就已经被压缩了(可以在webpack中完成)
- 兼容的浏览器在向服务器发送请求时,会告知服务器自己支持哪些压缩格式。
- 服务器在浏览器支持的压缩格式下,直接返回对应压缩后的文件,并在响应头中告知浏览器。
npm install compression-webpack-plugin -D
const webpack = require("webpack");
const CompressionPlugin = require("compression-webpack-plugin");
plugins: [
new webpack.optimize.ModuleConcatenationPlugin(),
new CompressionPlugin(),
],
部分属性
new CompressionPlugin({
include:"",
exclude:"",
threshold:0,//大于多少kb就压缩
minRatio:0.8,//代码压缩的最小比例
test:/\.(css|js)$/i,
}),
html压缩
HtmlWebpackPlugin 除了可以生成html模板外,还有其他配置可以对html进行压缩。
plugins: [
// new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "webpack项目",
template: "./src/index.html",
minify:isProduct?{
removeComments:true, //移除注释
removeEmptyAttributes:true,//移除空属性,例如class定一个,但是没有值。
removeRedundantAttributes:true,//移除默认属性,例如input的type 默认是text,设置后会移除type
collapseWhitespace:true,//折叠空白字符
minifyCSS:true ,//压缩内联样式的css
minifyJS:{ //压缩script标签中的js
mmangle:{
topLevel:true
}
}
}:false
}),
new DefinePlugin({
BASE_URL: "'./public'",
}),
],
打包时间的分析
npm i speed-measure-webpack-plugin -D
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smap = new SpeedMeasurePlugin();
smap.wrap(config)
打包后的文件分析
npm i webpack-bundle-analyzer -D
const {BundleAnalyzerPlugin} = require("webpack-bundle-analyzer");
plugins: [
// new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "webpack项目",
template: "./src/index.html",
minify: isProduct
? {
removeComments: true, //移除注释
removeEmptyAttributes: true, //移除空属性,例如class定一个,但是没有值。
removeRedundantAttributes: true, //移除默认属性,例如input的type 默认是text,设置后会移除type
collapseWhitespace: true, //折叠空白字符
minifyCSS: true, //压缩内联样式的css
minifyJS: {
//压缩script标签中的js
mmangle: {
topLevel: true,
},
},
}
: false,
}),
new DefinePlugin({
BASE_URL: "'./public'",
}),
new BundleAnalyzerPlugin(),
],
运行打包命令后会打开一个网页:
全部配置
com.config.js:
const path = require("path");
const { DefinePlugin } = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { merge } = require("webpack-merge");
const devConfig = require("./dev.config");
const prodConfig = require("./prod.config");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const {BundleAnalyzerPlugin} = require("webpack-bundle-analyzer");
const smap = new SpeedMeasurePlugin();
const config = function (isProduct) {
return {
entry: {
main: {
import: "./src/main.js",
dependOn: "shared",
},
index: {
import: "./src/index.js",
dependOn: "shared",
},
shared: "dayjs",
},
output: {
filename: "[name]-bundle.js",
path: path.resolve(__dirname, "../build"),
clean: true,
chunkFilename: "[name]-chunk.js", //对分包的文件命名
},
resolve: {
extensions: [".js", ".json", ".jsx", ".tsx", ".ts"],
alias: {
"@": path.resolve(__dirname, "../src"),
},
},
module: {
rules: [
{
test: /\.css$/,
use: [
isProduct ? MiniCssExtractPlugin.loader : "style-loader",
//"style-loader", 开发
// MiniCssExtractPlugin.loader,//生产
"css-loader",
"postcss-loader",
],
},
{
test: /\.scss$/,
use: [
isProduct ? MiniCssExtractPlugin.loader : "style-loader",
"css-loader",
"sass-loader",
],
},
{
test: /\.(png|jpe?g|gif|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024,
},
},
generator: {
filename: "img/[hash][ext]",
},
},
{
test: /\.jsx$/,
use: "babel-loader",
},
{
test: /\.ts$/,
use: "babel-loader",
},
{
test: /\.m?js$/,
exclude: /node_modules/, //排除/node_modules/ 下的文件
use: {
loader: "babel-loader",
},
},
{
test: /\.ts$/,
use: "babel-loader",
},
],
},
plugins: [
// new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "webpack项目",
template: "./src/index.html",
minify: isProduct
? {
removeComments: true, //移除注释
removeEmptyAttributes: true, //移除空属性,例如class定一个,但是没有值。
removeRedundantAttributes: true, //移除默认属性,例如input的type 默认是text,设置后会移除type
collapseWhitespace: true, //折叠空白字符
minifyCSS: true, //压缩内联样式的css
minifyJS: {
//压缩script标签中的js
mmangle: {
topLevel: true,
},
},
}
: false,
}),
new DefinePlugin({
BASE_URL: "'./public'",
}),
new BundleAnalyzerPlugin(),
],
};
};
module.exports = function (env) {
const isProduct = env.production;
let mergeConfig = isProduct ? prodConfig : devConfig;
const myConfig = merge(config(isProduct), mergeConfig);
return myConfig;
};
dev.config.js:
const path = require("path");
module.exports = {
mode: "development",
devServer: {
hot: true,
open: true,
port: "7070",
host: "127.0.0.1",
compress: true,
static: [
//静态目录
{
directory: path.join(__dirname, "public"),
},
{
directory: path.join(__dirname, "content"),
},
],
proxy: [
{
context: ["/api"],
target: "http://localhost:3000",
pathRewrite: { "^/api": "" },
},
],
},
performance: {
//配置如何展示性能提示 例如,如果一个资源超过 250kb,webpack 会对此输出一个警告来通知你。
maxEntrypointSize: 50000000,
maxAssetSize: 30000000,
},
};
prod.config.js:
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const { PurgeCSSPlugin } = require("purgecss-webpack-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
const webpack = require("webpack");
const path = require("path");
const glob = require("glob");
module.exports = {
mode: "production",
plugins: [
// new CleanWebpackPlugin(),
new CopyPlugin({
//把public下的文件拷贝到build下的public下
patterns: [{ from: "public", to: "public" }],
}),
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[name]_chunk.css", //异步导入的分包的css的名字
ignoreOrder: true, // 忽略 CSS 中的顺序问题
}),
new PurgeCSSPlugin({
paths: glob.sync(`${path.resolve(__dirname, "../src")}/**/*`, {
nodir: true,
}), //src/xx/x nodir:true,不是查找文件夹,而是文件
safelist: function () {
return {
standard: ["aa"], //白名单
// deep: [/^safelisted-deep-/],
// greedy: [/^safelisted-greedy/],
};
},
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new CompressionPlugin({}),
],
optimization: {
chunkIds: "deterministic", //选择模块 id 时需要使用哪种算法
usedExports: true, //去决定每个模块的到处内容是否被使用 ,生产环境下默认开启,与minimizer配合使用可以去除定义后没有使用的代码
runtimeChunk: {
name: "runtime", //运行时代码提取到单独的文件中的方式。这有助于避免在每个模块更改时导致运行时代码的变化,从而减少主要包的大小并提高缓存利用率。
},
//分包
splitChunks: {
chunks: "all",
//
maxSize: 20000,
//将包拆成不小于minSize的包,如果打不到minSize,那么这个包就不会拆分(会被合并到其他包中)
minSize: 10000,
cacheGroups: {
venders: {
//匹配/node_modules/下的包 [\\/] /node_modules和\node_modules 为了处理不同系统的问题
// \\ 第一个\是为了转意,有些字符有特殊含义
test: /[\\/]node_modules[\\/]/,
filename: "[id]_[contenthash:6]_vender.js",
},
foo: {
test: /utils/,
filename: "[id]_[contenthahs:6]_utils.js",
},
},
},
minimize: true, //在开发环境下启用 CSS 优化
//代码丑化设置
minimizer: [
new TerserPlugin({
extractComments: false,
terserOptions: {
compress: {
arguments: true,
unused: false,
},
mangle: true,
keep_fnames: true,
},
}),
new CssMinimizerPlugin({
parallel: true,
}),
],
},
};
package.json:
"scripts": {
"build": "npx webpack --config ./config/com.config.js --env production",
"server": "npx webpack server --config ./config/com.config.js --env development",
"ts-check": "tsc --noEmit",
"tc-check-watch": "tec --noEmit --watch",
},