Preface
Tree-shaking is a term in the front-end community, originally Rich Harris in Rollup. In a nutshell, Tree-shaking can make the final build of the project (Bundle) only include the code you actually need.
Moreover, when it comes to Tree-shaking, it is not inevitable to mention Dead Code Elimination. I believe many students will see descriptions such as this in some articles about Tree-shaking: Tree-shaking is a Dead Code Elimination (hereinafter collectively referred to as DCE) Technology.
So, now that there is the term DCE, why create a Tree-shaking term? Existence is valuable. Let's take a look at how Rich Harris answers this question.
1 Tree-shaking Vs Dead Code Elimination
At that time, Rich Haris wrote this article "Tree-shaking versus dead code elimination" specifically for this question. The article stated that the ultimate goals of DCE and Tree-shaking are the same (less code), but they are still There is a difference.
Rich Haris gave an example of making a cake, and pointed out that DCE is like mixing eggs directly when making a cake, and finally removing the egg shell from the finished cake. This is not perfect, while Tree-shaking is When making cakes, I only put in what I want, that is, I don’t put eggshells in and stir to make cakes.
Therefore, Tree-shaking does not mean to eliminate Dead Code, but to keep Live Code. Even if the final DCE and Tree-shaking results are the same, the actual process is different due to the limitations of JavaScript static analysis. And, including useful code can get better results, from the surface (making cake example) this is also a more logical approach.
In addition, at the time Rich Haris also thought that Tree-shaking might not be a good name, and considered using the phrase Live Code Inclusion to express it, but it seems to cause more confusion... Let's take a look at Rich Haris's Exact words:
I thought about using the ‘live code inclusion’ phrase with Rollup, but it seemed that I’d just be adding even more confusion seeing as tree-shaking is an existing concept. Maybe that was the wrong decision?
Therefore, I think that the students here should be clear that Tree-shaking and DCE are just the final result is the same , but the two are different from . Tree-shaking is to retain Live Code, while DCE is to eliminate Dead Code. .
Moreover, at the time Rich Harris also pointed out that Rollup is not perfect. The best result is to use Rollup + Uglify. However, it is clear that the current Rollup v2.55.1
has reached perfection. So, let’s take a look at the evolution of Tree-shaking along the timeline~
2 Evolution of Tree-shaking
When Tree-shaking was first proposed, it would only do one thing , which was to use the static import feature of ES Module to detect the export, import and use of the module content, so as to achieve the purpose of retaining the Live Code.
Maybe at this time you will ask if Tree-shaking will also eliminate Dead Code? Yes, but not necessarily. If you are using the current Rollup v2.55.1
, it will perform DCE, that is, eliminate Dead Code. However, if you are using Webpack, it is a different situation, it needs to use the corresponding plug-in Uglify to achieve DCE.
Below, we take Rollup as an example to talk about the past and present Tree-shaking.
2.1 Tree-shaking in the past
In the early days, when Rollup proposed and supported Tree-shaking, it did not do additional DCE. This can also be seen in the article written by Rich Haris in 15 years when he also advocated the use of Rollup + Uglify. So, here let us time of 1611334f64bc26 back to the Tree-shaking of Rollup v0.10.0
Going back to the v0.10.0
Rollup, you will find a very interesting point, that is, its GitHub README introduction is like this:
The name of Rollup comes from a rap song called "Roll up". I think this should be beyond the expectation of many students. However, Evan You also likes to rap, and then I (you) also like to rap, so this may prove that I (you) choose the front-end seems right? This song is attached here, you can choose to listen to this song to get closer to Rollup.
Portal: https://www.youtube.com/watch?v=UhQz-0QVmQ0
Below, we use the v0.10.0
to make a simple example to verify what we said earlier. And, in this process, you need to pay attention, if your Node version is too high, it will cause some incompatibility, so it is recommended to use Node v11.15.0
to run the following example.
First, initialize the dependencies of the project and installation base:
npm init -y
npm i rollup@0.10.0 -D
Then, create 3 files separately:
utils.js
export const foo = function () {
console.log("foo");
};
export const bar = function () {
console.log("bar");
};
main.js
import { foo, bar } from "./utils.js";
const unused = "a";
foo();
index.js
const rollup = require("rollup");
rollup
.rollup({
entry: "main.js",
})
.then(async (bundle) => {
bundle.write({
dest: "bundle.js",
});
});
Among them, main.js
is the entry file of the build, and then index.js
is responsible for using Rollup to build. It will write the final build result into the bundle.js
file:
// bundle.js
const foo = function () {
console.log("foo");
};
const unused = "a";
foo();
It can be seen in bundle.js
in retained utils.js
in foo()
function (because they were called), while imported uitls.js
in bar()
function (not called) is not retained , and defined variables ununsed
Although there is no Used, but still retained.
So, through such a small example, we can verify that Rollup's Tree-shaking does not support DCE at first. It only needed in the module you imported in the build result.
2.2 Current Tree-shaking
Before, we started to understand from the past Tree-shaking, and roughly established the first impression of Tree-shaking. Here we take a look at the current Rollup official introduction Tree-shaking
Tree-shaking, also known as Live Code Inclusion, refers to the process by which Rollup eliminates the actual unused code in the project. It is a method of Dead Code Elimination, but it is more effective than other methods in terms of output. The name is derived from the abstract syntax tree (Abstract Sytanx Tree) of the module. The algorithm first marks all related sentences, and then deletes all Dead Codes by shaking the syntax tree. It is similar in mind to the mark removal algorithm in GC (Garbage Collection). Although the algorithm is not limited to ES Module , they make it more efficient because it allows Rollup to treat all modules together as a large abstract syntax tree with shared bindings.
From this passage, we can easily find that over time, Rollup's definition of Tree-shaking is not only related to ES Module, but also supports DCE. So, sometimes we see some articles introducing Tree-shaking implementation like this:
- The ES Module can be used for static analysis The features of 1611334f64bf2e can be used to detect the export, import and use of the module content, and the Live Code is retained.
- Elimination of will not be executed. and have no side effects (Side Effect) , that is, the DCE process
So, we already know what Tree-shaking will do based on the characteristics of ES Module static analysis. So, let's take a closer look at point 2. From another perspective, it refers to when the code not executed , but it will have side effects , at this time, Tree-shaking will not eliminate this part of the code.
So, obviously building a good understanding of side effects can make the code in the project better by Tree-shaking. So, let's take a simple example to understand the side effects.
2.2.1 Side Effect
An introduction side effect (Side Effect) on the Wiki:
In computer science, if an operation, function, or expression modifies the value of some state variable outside of its local environment, it is said to have side effects.
Translate this passage into what we are familiar with, it means that when you modify not included in the current scope of , side effects will occur. Here we slightly modify the above example, sayHi()
function, and directly access the defined name
variable:
utils.js
export const name = "wjc";
export const sayHi = function () {
console.log(`Hi ${name}`);
};
main.js
import { sayHi } from "./maths.js";
sayHi();
Then, we use the REPL provided by Rollup to Tree-shaking this example. The output will be like this:
const name = "wjc";
const sayHi = function () {
console.log(`Hi ${name}`);
};
sayHi();
As you can see, here we did not directly import name
variable in the utils.js
file, but because name
outside its scope was accessed sayHi()
function, side effects occurred, so the final output will also have the name
variable.
Of course, this is just a very simple scenario that produces side effects, and it is also a mistake that many students will not make. In addition, a very interesting scenario is Class
keyword will have side effects after Babel is converted to ES5 code (in order to ensure that Class
Students who are interested in the above-mentioned problem can read this article Your Tree-Shaking is not useful understand carefully, I will not repeat the discussion here~
Concluding remarks
The motivation for writing this article is mainly because the two terms Tree-shaking and DCE are very similar, but Tree-shaking must have its meaning, so this article was born. Although the article does not cover the underlying implementation of Tree-shaking, I think sometimes is better than understanding the underlying implementation of figure out some vague concepts.
In addition, by comparing Rich Harris’ original intention of Tree-shaking in 2015, to the ability of Tree-shaking up to now, as time evolves, Rollup’s Tree-shaking also supports DCE by default, which will inevitably cause some The students' understanding of Tree-shaking was confused. Therefore, if you want to trace the origin (origin of Tree-shaking), I still recommend reading the article "Tree-shaking versus dead code elimination" carefully.
Finally, if there are improper or wrong expressions in the text, you are welcome to mention Issue~
like
By reading this article, if you have any gains, you can , this will be my motivation to continue to share, thank you~
I'm Wuliu, I like to innovate and tinker with the source code, focusing on the source code (Vue 3, Vite), front-end engineering, cross-end technology learning and sharing. In addition, all my articles will be included in https://github.com/WJCHumble/Blog , welcome to Watch Or Star!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。