代码压缩和tree_shaking

提示:看到我 请让我滚去学习


前言

压缩可以移除模块内部的无效代码
tree shaking 可以移除模块之间的无效代码


tree_shaking

背景

某些模块导出的代码并不一定会被用到

// myMath.js
export function add(a, b){
  console.log("add")
  return a+b;
}

export function sub(a, b){
  console.log("sub")
  return a-b;
}


// index.js
import {add} from "./myMath"
console.log(add(1,2));

tree shaking 用于移除掉不会用到的导出

使用

webpack2开始就支持了tree shaking

只要是生产环境,tree shaking自动开启

原理

webpack会从入口模块出发寻找依赖关系

当解析一个模块时,webpack会根据ES6的模块导入语句来判断,该模块依赖了另一个模块的哪个导出

webpack之所以选择ES6的模块导入语句,是因为ES6模块有以下特点:

  1. 导入导出语句只能是顶层语句
  2. import的模块名只能是字符串常量
  3. import绑定的变量是不可变的

这些特征都非常有利于分析出稳定的依赖

在具体分析依赖时,webpack坚持的原则是:保证代码正常运行,然后再尽量tree shaking

所以,如果你依赖的是一个导出的对象,由于JS语言的动态特性,以及webpack还不够智能,为了保证代码正常运行,它不会移除对象中的任何信息

因此,我们在编写代码的时候,尽量:

● 使用export xxx导出,而不使用export default {xxx}导出
● 使用import {xxx} from "xxx"导入,而不使用import xxx from "xxx"导入

依赖分析完毕后,webpack会根据每个模块每个导出是否被使用,标记其他导出为dead code,然后交给代码压缩工具处理

代码压缩工具最终移除掉那些dead code代码

CommonJS 不直接支持 tree shaking。Tree shaking 是一个由 ES6 模块引入的概念,它允许在构建过程中删除未使用的代码。由于 CommonJS 模块在运行时解析,因此无法在编译时确定哪些导出未被使用。然而,一些现代打包工具(如 Webpack 和 Rollup)可以在某些情况下实现 CommonJS 的 tree shaking,但这通常不如 ES6 模块有效。

使用第三方库

某些第三方库可能使用的是commonjs的方式导出,比如lodash
又或者没有提供普通的ES6方式导出
对于这些库,tree shaking是无法发挥作用的

因此要寻找这些库的es6版本,好在很多流行但没有使用的ES6的第三方库,都发布了它的ES6版本,比如lodash-es

lodash-es使用示例:

import { shuffle, cloneDeep, throttle, debounce } from 'lodash-es'

作用域分析

tree shaking本身并没有完善的作用域分析,可能导致在一些dead code函数中的依赖仍然会被视为依赖
插件webpack-deep-scope-plugin提供了作用域分析,可解决这些问题

副作用问题

webpack在tree shaking的使用,有一个原则:一定要保证代码正确运行
在满足该原则的基础上,再来决定如何tree shaking
因此,当webpack无法确定某个模块是否有副作用时,它往往将其视为有副作用
因此,某些情况可能并不是我们所想要的

//common.js
var n  = Math.random();

//index.js
import "./common.js"

虽然我们根本没用有common.js的导出,但webpack担心common.js有副作用,如果去掉会影响某些功能

如果要解决该问题,就需要标记该文件是没有副作用的

在package.json中加入sideEffects

{
    "sideEffects": false
}

有两种配置方式:

● false:当前工程中,所有模块都没有副作用。注意,这种写法会影响到某些css文件的导入
● 数组:设置哪些文件拥有副作用,例如:[“!src/common.js”],表示只要不是src/common.js的文件,都有副作用

这种方式我们一般不处理,通常是一些第三方库在它们自己的package.json中标注

代码压缩

背景

  1. 为什么要进行代码压缩

    减少代码体积;破坏代码的可读性,提升破解成本;

  2. 什么时候要进行代码压缩

    生产环境

  3. 使用什么压缩工具

    目前最流行的代码压缩工具主要有两个:UglifyJs和Terser

UglifyJs:是一个传统的代码压缩工具,已存在多年,曾经是前端应用的必备工具,但由于它不支持ES6语法,所以目前的流行度已有所下降。

Terser:一个新起的代码压缩工具,支持ES6+语法,因此被很多构建工具内置使用。webpack安装后会内置Terser,当启用生产环境后即可用其进行代码压缩。

Terser

在Terser的官网可尝试它的压缩效果

Terser官网:https://terser.org/

webpack+Terser

webpack自动集成了Terser
如果你想更改、添加压缩工具,又或者是想对Terser进行配置,使用下面的webpack配置即可

const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
  optimization: {
    // 是否要启用压缩,默认情况下,生产环境会自动开启
    minimize: true, 
    minimizer: [ // 压缩时使用的插件
      new TerserPlugin(), 
    ],
  },
};
``
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值