讲一讲Webpack tree-shaking的触发机制

一、tree-shaking是什么?

这个词应该大家都不陌生了,翻译过来就是"树摇"。

看一下官方的解释:

Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. It relies on the static structure of ES2015 module syntax, i.e. import and export. The name and concept have been popularized by the ES2015 module bundler rollup.

简言之,tree-shaking有助于我们减少打包后产物的体积,去掉无用的代码。这里不多说概念,本文的重点还是在于文章标题,我们关注的是webpacktree-shaking能力以及触发条件。

二、搭建Webpack环境

创建项目

cmd 复制代码
mkdir tree-shaking-webpack && cd tree-shaking-webpack

使用pnpm初始化package.json

cmd 复制代码
pnpm init

安装webpackwebpack-cli

cmd 复制代码
pnpm add webapack webpack-cli -D

创建webpack.config.js配置文件

javascript 复制代码
// webpack.config.js

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "bundle.js",
  },
};

修改package.json

json 复制代码
{
  "name": "tree-shaking-webpack",
  "version": "1.0.0",
  "description": "",
  "main": "./src/main.js", // 修改入口
  "scripts": {
    "build": "webpack --config ./webpack.config.js" // 增加build命令
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4"
  }
}

创建入口文件

javascript 复制代码
// src/main.js

console.log('hello wolrd')

执行build命令,可以看到已经打包成功了

但是控制台报了个警告,原因是没有配置mode,我们配置mode为开发模式development即可

javascript 复制代码
// webpack.config.js

const path = require("path");

module.exports = {
  mode: "development", //开发模式
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "bundle.js",
  },
};

再次执行build,控制台不再报错

三、webpack的tree-shaking

1、通过ES6的import和export触发

根据前面tree-shaking介绍中提到,tree-shaking其实依赖了ES6中的importexport

所以如果我们先做第一个尝试:commonJS是否支持tree-shaking

我们新增个compute.js文件

javascript 复制代码
// src/compute.js

const add = (a, b) => {
  return a + b;
};

const sub = (a, b) => {
  return a - b;
};

module.exports = {
  add,
  sub,
};

main.js中引用compute.js,并且只使用add方法

javascript 复制代码
const { add, sub } = require("./compute");

console.log(add(1, 2));

执行打包后,发现main.jssub方法也被打打包了

我们换成ES6规范的导入和导出

javascript 复制代码
// src/compute.js

export default {
  add,
  sub
}

// src/main.js

import { add, sub } from './compute.js'

执行打包,main.js中不再出现sub方法

所以得出结论,如果要触发tree-shaking,需要通过ES6importexport触发。

2、通过解构的方法触发

在满足第一点的条件下,我们试想一下,如果我们是import整个对象,是否会触发tree-shaking呢?例如:

javascript 复制代码
import compute from './compute'

console.log(compute.add(1,2))

因为这个案例的打包文件体积比较小,我们看不太出来,我们尝试安装一个lodash来试一下,需要注意的是,我们需要安装的是lodashESM版本,即lodash-es,否则官方默认的lodashcommonJS规范

cmd 复制代码
pnpm add lodash-es

修改main.js的内容

javascript 复制代码
// src/main.js

import { get } from "lodash-es";

console.log(get({ a: 1 }, "a"));

执行打包,并创建index.html文件引入打包后的bundle.js

打开index.html,查看bundle.js的体积大小为103kb

如果我们不使用解构的方式,直接引入整个lodash,然后打包

javascript 复制代码
// src/main.js

import _ from "lodash-es";

console.log(_.get({ a: 1 }, "a"));

再次打包后,可以看到,bundle.js的体积大小已经来到了恐怖的1.6MB

经过tree-shaking之后,bundle.js只打包了lodashget方法,其他无关的方法都被"摇走了"

所以得出结论,如果要触发tree-shaking,需要通过解构的方式触发。

3、开启production模式

细心的同学其实可以发现,上面第一点案例中,通过import的方式导入了compute.js文件,main.js代码中虽然没有了sub方法,但是compute.js依然会把sub方法打包

这是因为webpack对同一文件中的tree-shaking必须要开启production模式才能生效

javascript 复制代码
// webpack.config.js

const path = require("path");

module.exports = {
  mode: "production", //生产模式
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "bundle.js",
  },
};

再次执行打包,发现sub方法已经不存在了,而且代码还进行了压缩

4、总结

通过上面的几个案例,webpack如果要实现tree-shaking必须满足以下几个条件:

  1. 通过ES6importexport,包括npm包也必须是ESM
  2. 通过解构的方式引入
  3. 同一文件下,需要开启production模式
相关推荐
涔溪42 分钟前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
榴莲千丞1 小时前
第8章利用CSS制作导航菜单
前端·css
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与1 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
guokanglun1 小时前
CSS样式实现3D效果
前端·css·3d
咔咔库奇1 小时前
ES6进阶知识一
前端·ecmascript·es6
渗透测试老鸟-九青2 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss
龙猫蓝图2 小时前
vue el-date-picker 日期选择器禁用失效问题
前端·javascript·vue.js
fakaifa2 小时前
CRMEB Pro版v3.1源码全开源+PC端+Uniapp前端+搭建教程
前端·小程序·uni-app·php·源码下载
夜色呦2 小时前
掌握ECMAScript模块化:构建高效JavaScript应用
前端·javascript·ecmascript