webpack-打包优化相关知识

1,067 阅读4分钟

TerserPlugin

  • 底层:TerserPlugin 底层使用 terser 这个库来进行压缩代码

  • 作用:压缩、丑化我们的代码,让我们打包之后的包体积更小。在 webpack 中 mode 设置成production,webpack 默认帮我们开启这个配置,我们也可以自己进行自定义配置

  • 用法: 一些常见的配置

webpack.config.js

const TerserWebpackPlugin = require('terser-webpack-plugin');

module.exports {
	minimize: true,
	// 配置代码优化
	minimizer: [
		// JS压缩的插件: TerserWebpackPlugin
		new TerserWebpackPlugin({
			// 注释是否需要提取到单独文件中(默认为true)
			extractComments: false,
			// 使用多进程并发运行构建,可以提高构建速度(默认为开启,个数为 CPU-1)
			parallel: true,
			// 配置 terser 插件的选项
			terserOptions: {
				// 配置代码压缩选项
				compress: {
					// 压缩arguments取值
					arguments: true,
					// 没用到的代码直接删除
					unused: true
				},
				// 开启变量名称压缩(需要开启)
				mangle: true,
				// 顶层变量名称压缩(最外层作用域的变量名称压缩)
				toplevel: true,
				// 保持函数名称命名
				keep_fnames: true
			}
		}),
	]
}

CssMinimizerWebapckPlugin

  • 底层:CssMinimizerWebapckPlugin 底层使用 cssnano 这个库来压缩我们的 css 代码

  • 作用:压缩、丑化CSS 样式,删除注释等

  • 用法:需要配合 MiniCssExtractPlugin 插件一起使用

webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerWebapckPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  minimize: true,
  minimizer: {
    // CSS压缩插件: CssMinimizerWebapckPlugin
	  new CssMinimizerWebapckPlugin({
		  minimizerOptions: {
			  preset: [
				  'default',
				  {
					  // 删除注释
					  discardComments: { removeAll: true }
				  }
			  ]
		  }
	  })
  },
  plugins: [
    new MiniCssExtractPlugin({
			filename: 'css/[name].css',
			chunkFilename: 'css/[name]_chunk.css'
		})
  ]
}

TreeShaking

webpack 默认打包时对于入口文件会做 TreeShaking 的操作,删除一些永远不会执行或者不被使用的代码,对于导入的模块就不知道该怎么做,可以通过两个配置来实现对模块的 TreeShaking 操作

usedExports

  • 作用:用于做 TreeShaking 的配置,在 production 环境下默认为 true,在 webpack 打包时会对导出的模块进行解析会给无用的代码进行标记,之后在配置 TerserPlugin 根据标记来删除无用的代码达到 TreeShaking 的效果。

  • 用法:

utils.js

// 使用了 sum 函数,sum函数将会被打包
export const sum = (num1, num2) => num1 + num2
/**
 * 导入了这个文件但是没有使用过这个函数,如果 usedExport 设置为 true
 * 这个函数就会被标记,被 webpack 添加一个魔法注释告知压缩工具这个函数可以被删除
 * 在打包后的文件中会被添加上这个一段注释 (unused harmony export mul),并且直接移除了导入的代码
 */
export const mul = (num1, num2) => mun1 * num2

main.js(入口文件中)

import { sum } from './utils.js'
console.log(sum(10, 20))

webpack.config.js

module.exports = {
  usedExports: true,
  minimize: true,
  minimizer: {
	new TerserWebpackPlugin({
		terserOptions: {
			compress: {
        // 删除无用代码
				unused: true
			},
		}
  },
}

sideEffects

  • 作用: webpack 会根据这个去判断哪些导出的代码没有被使用或者没有产生副作用,在打包的时候就直接删除

  • 用法:

package.json

{
	// 设置 false 告知 webpack 所有模块都没有副作用
	"sideEffects": false
}

OR

{
	// 也可以设置数组,传入文件路径,告知 webpack 这些文件是有副作用的,这些文件将不会被删除
	"sideEffects": [
		// ...你产生副作用的代码路径
	]
}

utils.js

export const sum = (num1, num2) => num1 + num2
export const mul = (num1, num2) => mun1 * num2

main.js(入口文件中)

// 导入了 utils.js,但是模块里的东西都没有被使用
// sideEffect 设置为 true,utils.js 里的代码会被直接删除
import './utils.js'

PugreCssWebpackPlugin

作用: 用于 css 样式 TreeShaking, 需要配合 MiniCssExtractPlugin 插件一起使用

module.exports = {
	plugins: [
		// 将 css 样式提取到一个独立的css文件
		new MiniCssExtractPlugin({
			filename: 'css/[name].css',
			chunkFilename: 'css/[name]_chunk.css'
		}),
		// css TreeShaking 插件
		new PurgeCSSPlugin({
			paths: glob.sync(`${path.resolve(__dirname, '../src')}/**/*`, { nodir: true })
		})
	]
}

Scope Hoisting

作用: 让 Webpack 打包后的代码更小,运行更快

const webpack = require('webpack');
module.exports = {
	plugins: [
		// 作用域提升
		new webpack.optimize.ModuleConcatenationPlugin()
	]
}

HTTP 压缩

作用: 使文件再进一步压缩,让文件体积更小

过程:

  • 第一步: 在 webpack 中将文件打包成对应的压缩格式类型。
  • 第二步: 支持压缩格式的浏览器会告诉服务器我支持那种压缩格式。
  • 第三步: 服务器会在浏览器支持压缩的情况下直接返回压缩格式的内容并告诉浏览器我这次给你的是这个压缩格式的内容

Webpack.config.js

module.exports = {
	plugins: [
		// 开启打包压缩优化
		new CompressionWebpackPlugin({
			test: /\.(css|js)$/, // 匹配哪些文件需要压缩
			minRatio: 0.7, // 压缩比例
			algorithm: 'gzip', // 打包算法
			// threshold: 70000 // 大于设置的大小才压缩
		})
	]
}

HTML 压缩

作用: 对 HTML 文件进行压缩,减少打包体积

Webpack.config.js

module.exports = {
	plugins: [
		new HtmlWebpackPlugin({
			template: './src/index.html',
			// 只有 HTML 改变才会重新生成
			cache: true,
			// 默认会使用 html-minifier-terser
			minify: {
					// 移除注释
					removeComments: true,
					// 移除空属性
					removeEmptyAttributes: true,
					// 移除默认属性
					removeRedundantAttributes: true,
					// 折叠空格
					collapseWhitespace: true,
					// 压缩内联CSS
					minifyCSS: true,
					// 压缩Script标签中的js
					minifyJS: true
				}
		})
	]
}

打包分析

SpeedMeasureWebpackPlugin

作用: 查看每个包打包时间

const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasureWebpackPlugin();

module.exports = function() {
	return smp.wrap(config) // 传入你的webpack配置
}

WebpackBundleAnalyzer

作用: 查看打包后的文件大小

Webpack.config.js

const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
	plugins: [
		// 对打包后的结果进行分析
		new BundleAnalyzerPlugin()
	]
}