温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

JS加载性能Tree Shaking优化的方法是什么

发布时间:2022-11-15 09:27:01 来源:亿速云 阅读:98 作者:iii 栏目:开发技术

这篇文章主要介绍了JS加载性能Tree Shaking优化的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JS加载性能Tree Shaking优化的方法是什么文章都会有所收获,下面我们一起来看看吧。

什么是 Tree Shaking

您可以将应用程序想象成一棵树。您实际使用的源代码和库表示树中绿色的活叶子,死代码表示秋天时树上棕色的枯叶,为了除掉枯叶,你必须摇动树,让它们掉下。Tree Shaking 是指消除死代码,下面通过一个应用程序演示了这个概念。使用 ES6 静态模块语法导入依赖项:

// 在这里导入了所有的数组处理方法
import arrayUtils from "array-utils";

在应用最初的时候,依赖项可能很少,随着功能逐渐增加,依赖项也会增加,更糟糕的是,旧的依赖项不再使用,但可能不会从代码库中删除,最终的结果是,应用程序带有大量未使用的 JS 代码,Tree Shaking 解决了这个问题,它通过分析我们在文件中使用的 ES6 静态模块语句来分析哪些模块被导入了:

// 只导入部分方法
import { unique, implode, explode } from "array-utils";

这个导入示例与前一个示例的区别在于,本示例只导入模块的特定部分,而不是从“array-utils”模块导入所有内容。

寻找 Tree Shaking 的机会

为了便于说明,这里有一个使用 webpack 的单页应用程序示例来演示 Tree Shaking 是如何工作的。界面如下:

这个程序打包之后的代码被分为两文件,如下:

在任何应用程序中,你需要从静态导入语句寻找 Tree Shaking 的机会,在示例程序中(FilterablePedalList.js)你将看到这样一行导入语句:

import * as utils from "../../utils/utils";

在文件中这样的导入语句应该引起你的注意,它的意思是:从 utils 模块导入所有内容。问题是:你真的用到所有的内容了吗?现在我们来检查 FilterablePedalList.js 中究竟使用了 utils 模块中的那些方法,通过检索发现只使用了 utils.simpleSort:

if (this.state.sortBy === "model") {
  // Simple sort gets used here...
  json = utils.simpleSort(json, "model", this.state.sortOrder);
} else if (this.state.sortBy === "type") {
  // ..and here...
  json = utils.simpleSort(json, "type", this.state.sortOrder);
} else {
  // ..and here.
  json = utils.simpleSort(json, "manufacturer", this.state.sortOrder);
}

我们现在开始做 Tree Shaking 优化

防止 Babel 将 ES6 模块转换为 CommonJS 模块

在大型应用中 Babel 是不可或缺的工具,但是它会让 Tree Shaking 变得困难。如果你正在使用 babel-preset-env,它会自动为你将 ES6 模块转换为更广泛兼容的 CommonJS 模块,即:用 require 代替 import。对于 CommonJS 模块而言做 Tree Shaking 优化非常困难,这是因为 CommonJS 模块是动态的,在构建阶段 bundlers 不容易分析出 CommonJS 模块导出了什么和导入了什么。为了避免 babel-preset-env 将 ES6 模块转换成 CommonJS 模块,我们可以这么做:

{
  "presets": [
    ["env", {
      "modules": false
    }]
  ]
}

在你的 Babel -preset-env 配置中简单指定"modules": false 就可以让 Babel 按照我们想要的方式运行,这允许 webpack 分析你的依赖树并摆脱那些未使用的依赖。

留意 side effects

当函数修改了它作用域之外的内容,我们就认为这个函数有 side effects。side effects 也适用于ES6模块,在你做 Tree Shaking 的时候你需要留意你的模块是否有 side effects(副作用),如果模块接受可预测的输入,并输出同样可预测的输出,而不修改其自身范围之外的任何内容,我们就认为这个模块没有 side effects,对于没有 side effects 的模块你可以放心的做 Tree Shaking。在这里我举两个 side effects 例子:

import './index.module.scss';
import './assets/shoot.svg';

如果在某个模块中出现了上面这样的 import 语句,则认为这个模块有 side effects,这时在做 Tree Shaking 的时候你需要小心一些。默认情况下,webpack 在做 Tree Shaking 的时候,会认为 index.module.scss 与 assets/shoot.svg 没有被用到,所以它们会被移除,如果不想被移除,可以告诉 webpack 它们是 side effects:

{
  "name": "webpack-tree-shaking-example",
  "version": "1.0.0",
  "sideEffects": [
    "./index.module.scss",
    "./assets/shoot.svg"
  ]
}

在项目的 package.json 中配置 sideEffects 字段。sideEffects 字段也能为 false,这表示项目中不存在有 side effects 的模块。

只导入你需要的

现在我们已经告诉 babel 不要将 ES6 模块转成 CommonJS 模块,现在我们需要对导入语法做一点微调,只从 utils 模块中引入我们需要的函数吗,在本指南的例子中,我们只需要 simpleSort:

import { simpleSort } from "../../utils/utils";
if (this.state.sortBy === "model") {
  json = simpleSort(json, "model", this.state.sortOrder);
} else if (this.state.sortBy === "type") {
  json = simpleSort(json, "type", this.state.sortOrder);
} else {
  json = simpleSort(json, "manufacturer", this.state.sortOrder);
}

现在我们已经完成了 Tree Shaking 的工作,下面是 Tree Shaking 之前 webpack 打包生成的 js 包大小:

                 Asset      Size  Chunks             Chunk Names
js/vendors.16262743.js  37.1 KiB       0  [emitted]  vendors
   js/main.797ebb8b.js  20.8 KiB       1  [emitted]  main

下面是 Tree Shaking 之后 webpack 打包生成的 js 包大小:

                 Asset      Size  Chunks             Chunk Names
js/vendors.45ce9b64.js  36.9 KiB       0  [emitted]  vendors
   js/main.559652be.js  8.46 KiB       1  [emitted]  main

main 的文件大小下降比较明显,这是因为 webpack 移除了不需要的 utils 方法。

更复杂的情况

在有些情况你按照上面的步骤进行 Tree Shaking,但是 webpack 还是将模块的所有内容都打包到最终的 Chunk 中了,例如:lodash。

// 仍然会导入所有的内容
import { sortBy } from "lodash";
// 这只会导入 sortBy
import sortBy from "lodash/sortBy";

如果你想要使用第一种写法,那么你还需要安装 babel-plugin-lodash。如果你使用了第三方库,你可以看一下这个库的导出是否使用了 ES6 语法,如果它的导出用的是 CommonJS 语法,例如:module.exports,那么 webpack 不能对它进行 Tree Shaking 优化。有些插件,例如:webpack-common-shake,提供了对 CommonJS 模块进行 Tree Shaking 的能力,但是它有一些限制。

关于“JS加载性能Tree Shaking优化的方法是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“JS加载性能Tree Shaking优化的方法是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI