评论

[生存指南]关于打包工具webpack和vite的摇树优化(Tree Shaking)

由于大环境的“卷”,对前端优化有了更高的要求,摇树优化成为必须了解的知识

摇树 Tree Shaking是什么?

摇树优化(Tree Shaking)是Webpack中一种用于优化JavaScript代码的技术。它的目标是通过静态分析,从代码中剔除未被使用的模块,从而减少最终打包文件的大小。

在一个大型的JavaScript应用程序中,通常会引入多个模块和库,但并不是所有的模块都会被使用到。如果没有进行优化,所有引入的模块都会被打包到最终的输出文件中,导致文件变得很大,加载时间变长,影响应用的性能。在以往导入导出有时候是动态的,难以预测的,所以需要通过规范来约束和优化性能。

1、基于ES module 用到才引用

//拿常用的'element-ui'举例
import * as ElementUI from 'element-ui'  //这是一种糟糕的方式
import {Submenu,CascaderTable,TableColumn } from 'element-ui' //用到什么引入什么 

使用ES6模块化:摇树优化要求代码使用ES6模块化的语法。确保你的代码基于ES6模块化进行编写,而不是使用CommonJS或AMD等其他模块化方案。

2、设置sideEffects

在Webpack中,sideEffects是一个用于优化打包输出的配置选项。它用于指示哪些模块具有 副作用,或者说哪些模块是否会对整个应用程序的行为产生影响,以便Webpack可以进行更有效的处理。

设置sideEffects的目的是告诉Webpack哪些模块没有副作用,以便它可以在打包过程中优化代码。Webpack可以根据这些信息,例如删除未使用的导入、通过摇树优化(tree-shaking)消除未使用的代码等。

sideEffects的设置方式有两种:

2.1 在模块的package.json文件中设置:

{
  "name": "your-project",
  "sideEffects": false
}

将sideEffects设置为false表示该模块没有副作用。如果你确定某个模块没有副作用,可以将其设置为false,以便Webpack可以进行相应的优化。

2.2 在Webpack配置文件中的module.rules中使用sideEffects选项:

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        sideEffects: false
      }
    ]
  }
};

在相应的规则中,通过将sideEffects设置为false来指定该规则匹配的文件没有副作用。

请注意,设置sideEffects为false可能会导致一些副作用的代码被错误地删除,因此在使用时要谨慎。确保你了解你的代码,并进行适当的测试,以确保没有重要的副作用被错误地优化掉。

2.3 配置副作用文件,避免打包压缩的时候误删

"sideEffects": [
    "./src/common.js",
    "*.css" 
]

在实际过程中,我们会发现,有些css模块是全局,因为没有申明副作用,也一起被移除,所以需要单独排除掉,比如 global.css模块都没被打包。因为它们都算是副作用模块,而我们在package.json中声明了没有副作用,所以它们就被移除了。

3、配置mode的状态来唤醒摇树优化

配置modeproduction:在Webpack的配置中,将mode设置为production模式。这会自动启用一系列的优化功能,包括摇树优化。

使用Webpack的TerserPluginTerserPlugin是一个用于压缩和混淆JavaScript代码的Webpack插件。它内置了摇树优化功能,并可以通过配置选项进行进一步的优化。确保在Webpack配置中使用TerserPlugin并进行正确的配置。

4、babel-loader使Tree-shaking失效

使用Babel Loader确实有可能导致Tree-shaking失效,这是因为Babel Loader默认情况下会将所有ES6模块转换为CommonJS模块,而CommonJS模块的导入和导出方式是动态的,无法在编译时进行静态分析。

为了解决这个问题,你需要在Babel配置中进行相应的调整,以保持ES6模块的静态导入和导出,从而使Tree-shaking能够正常工作。

首先,确保你安装了@babel/preset-env插件,并在Babel配置文件(通常是.babelrc或babel.config.js)中进行如下配置:

{
  "presets": [
    ["@babel/preset-env", {
      "modules": false
    }]
  ]
}

在上述配置中,将modules选项设置为false,以保持ES6模块的形式。这样Babel在转换代码时就不会将ES6模块转换为CommonJS模块。

通过pure标记一些只在开发环境中,但生产环境不需要的代码

var test = /*#__PURE__*/function () {
  return 996;
}();

在Babel 6之后的版本可以用 /*#__PURE__*/ 注释,这样在做副作用检查的时候,就可以认为该方法没有副作用,标记为"纯函数",方便删除。这样的好处在于一些特别的测试数据不会出现在线上环境中~

最后一次编辑于  2023-08-11  
点赞 0
收藏
评论
登录 后发表内容