preface
Tree-shaking is a term in the front-end community that was first coined by Rich Harris in Rollup. In a nutshell, tree-shaking can make a project’s final build Bundle contain only the code you actually need.
Dead Code Elimination Does not take place when talking about Tree-shaking. Tree-shaking does not take place when talking about Tree-shaking. Tree-shaking is a Dead Code Elimination (DCE) technology.
So, given the term DCE, why make a tree-shaking term? Let’s take a look at Rich Harris’s answer to this question.
1 Tree-shaking Vs Dead Code Elimination
At the time, Rich Haris wrote tree-Shaking Versus Dead Code Elimination in response to this question, suggesting that DCE and tree-shaking ultimately have the same goal (less code). But there are still differences.
Rich Haris gives an example of cake making. He points out that DCE is like putting eggs in the mix when making cakes, and then taking out the shells in the cake. It is not perfect, while tree-shaking is putting only what I want in the cake, not putting the shells in the mix when making cakes.
Therefore, tree-shaking does not mean eliminating Dead Code, but preserving Live Code. Even though the final DCE and tree-shaking results are the same, the actual process is different due to the limitations of JavaScript static analysis. Also, including useful code yields better results, and on the face of it (the cake-making example) is a more logical approach.
In addition, at the time, Rich Haris thought tree-shaking might not be a good name and considered using the phrase Live Code Inclusion, but it seemed to cause more confusion…… Here’s what Rich Haris said:
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?
Tree-shaking is the same as DCE, but the process is different. Tree-shaking preserves Live Code, while DCE removes Dead Code.
Moreover, Rich Harris also pointed out that Rollup is not perfect, and the best result is to use Rollup + Uglify. However, it is clear that Rollup V2.55.1 is now perfect. So let’s look at the evolution of tree-shaking along the timeline
2 Tree-shaking evolution
Tree-shaking when it was first proposed, it only did one thing: it kept Live Code by taking advantage of the ES Module static import feature to detect how Module content was exported, imported, and used.
Tree-shaking also eliminates Dead Code, you might ask. True, but not necessarily, if you’re using Rollup V2.55.1 now, it does DCE, which eliminates Dead Code. However, if you are using Webpack, it is a different story and requires the Uglify corresponding plug-in to implement DCE.
Let’s talk about tree-shaking, past and present, using Rollup as an example.
2.1 Tree-shaking in the past
In the early days, when Rollup proposed and supported tree-shaking, it did not do additional DCE, as can be seen from Rich Haris’s article in 2015, when he also advocated Rollup + Uglify. So let’s rewind the time to tree-shaking in Rollup V0.10.0.
Going back to Rollup V0.10.0, it’s interesting to note that the GitHub README introduction looks like this:
Rollup was named after a rap song called “Roll Up”, which I think surprised a lot of students. But Evan You like to rap, and I like to rap, so maybe it’s an argument that I (You) did the right thing with the front end? The song is attached here and you can choose to listen to it to get closer to Rollup.
Portal: www.youtube.com/watch?v=UhQ…
Let’s verify this with a simple example using Rollup V0.10.0. Also, be aware of the incompatibilities that may occur if your Version of Node is too high, so it is recommended to run the following example using Node V11.15.0.
First, initialize the project and install base dependencies:
NPM init -y NPM I [email protected] -dCopy the code
Then, create 3 files respectively:
utils.js
export const foo = function () {
console.log("foo");
};
export const bar = function () {
console.log("bar");
};
Copy the code
main.js
import { foo, bar } from "./utils.js";
const unused = "a";
foo();
Copy the code
index.js
const rollup = require("rollup");
rollup
.rollup({
entry: "main.js",
})
.then(async (bundle) => {
bundle.write({
dest: "bundle.js"}); });Copy the code
Where main.js is the entry file for the build, and index.js is responsible for the build using Rollup, which writes the final build to the bundle.js file:
// bundle.js
const foo = function () {
console.log("foo");
};
const unused = "a";
foo();
Copy the code
As you can see, the foo() function in utils.js is preserved in bundle.js (because it was called), while the bar() function in imported uitls.js (which was not called) is not, and the variable defined ununsed is not used, But it’s still there.
So, with a small example like this, we can verify that Rollup’s tree-shaking does not initially support DCE, it simply preserves the code you need in imported modules in the build result.
2.2 Tree-shaking now
Above, we started with tree-shaking in the past, and built up a general impression of tree-shaking. Tree-shaking Rollup Tree shaking Rollup Tree shaking Rollup Tree shaking
Tree-shaking, also known as Live Code Inclusion, is the process of Rollup to eliminate Code that is not actually used ina project. It is a method of Dead Code Elimination, but is more efficient at output than other methods. The name comes from the Abstract syntax Tree of the module. The algorithm first marks all related statements and then removes all Dead codes by shaking the syntax tree. It is similar in idea to the tag clearing algorithm in Garbage Collection. Although these algorithms are not limited to ES Modules, they make them more efficient because they allow Rollup to treat all modules together as a large abstract syntax tree with shared bindings.
Over time, Rollup’s definition of tree-shaking has become more than just ES Module related; it also supports DCE. So, sometimes we see articles describing tree-shaking implementations like this:
- Using ES Module can carry out static analysis features to detect Module content export, import and be used, retain Live Code
- Eliminate Dead Code, or DCE process, that will not be executed and has no Side effects
So, we already know what tree-shaking does based on the static analysis features of the ES Module. So, let’s take a closer look at point 2. From another perspective, it means that when code is not being executed, but it has side effects, tree-shaking does not remove it.
Clearly, having a good understanding of side effects makes the code in your project tree-shaven better. So, let’s look at a simple example to understand the side effects.
2.2.1 Side Effect
Side Effects are described on the Wiki:
In computer science, an operation, function, or expression is said to have a side effect if it modifies the value of some state variable outside of its local environment.
When you change the value of a variable that is not included in the current scope, it can cause side effects. Here we modify the above example a bit by dropping the sayHi() parameter and calling the name variable directly:
utils.js
export const name = "wjc";
export const sayHi = function () {
console.log(`Hi ${name}`);
};
Copy the code
main.js
import { sayHi } from "./maths.js";
sayHi();
Copy the code
We then tree-shaking the example through the REPL provided by Rollup. The output would look like this:
const name = "wjc";
const sayHi = function () {
console.log(`Hi ${name}`);
};
sayHi();
Copy the code
As you can see, we don’t import the name variable directly from the utils.js file, but the sayHi() function has the side effect of accessing the name variable outside its scope, so the final output will have the name variable as well.
Of course, this is only a very simple side effect scenario, and many students will not make the mistake. In addition, one interesting scenario is that classes declared using the Class keyword can have side effects after Babel converts them into ES5 code (to make classes enumerable).
For those of you who are interested in this question, your tree-shaking is not helpful
conclusion
The main motivation for writing this article is that the terms tree-shaking and DCE are very similar, but tree-shaking certainly has a reason to exist, hence this article. Although there is no tree-shaking underlying implementation in this article, I think sometimes it is better to understand the priorities of vague concepts than to understand the underlying implementation.
Moreover, compared with the original intention of Tree-shaking proposed by Rich Harris in 2015, tree-shaking has been able to support DCE by default over time. It is also inevitable that some students may have a confused understanding of tree-shaking. So, if you want to take a closer look at tree-shaking Versus Dead Code Elimination, I recommend taking a closer look at tree-shaking Versus Dead Code Elimination.
Finally, if there is any improper expression or mistake in the article, please make an Issue
give a like
If you get something from this post, please give me a “like”. This will be my motivation to keep sharing. Thank you
My name is Wu Liu. I like innovation and source Code manipulation, and I focus on source Code (Vue 3, Vite), front-end engineering, cross-end and other technology learning and sharing. Welcome to follow my wechat official account: Code Center.