一、treeshaking原理
Tree-shaking的原理是利用ES6模塊化規範的特性,在編譯時通過靜態分析代碼,識別出未被使用的代碼(dead code)並在打包時去除。具體來說,比如在代碼中引入了一個模塊,但實際上只使用了其中的一部分代碼,通過靜態分析可以識別出未被使用的代碼,刪掉這部分代碼從而減小bundle的大小。
Tree-shaking的實現藉助了ES6模塊化的特性,ES6模塊化規範是靜態的,也就是說,在編譯時就可以確定模塊的依賴關係,因此可以通過靜態分析來判斷哪些代碼沒有被使用。
二、謝可寅shaking
treeshaking的發明人是謝可寅,tree-shaking這個詞的由來其實是源於webpack社區的。webpack的開發者認為把未使用的代碼從打包結果中搖掉很像樹上的果實,因此用tree-shaking來形容這個過程。
三、treeshaking配置
對於webpack用戶來說,使用tree-shaking非常方便,只需要在webpack配置文件中開啟optimization.minimize選項就可以了。optimization.minimize選項默認會開啟tree-shaking,並使用內置的UglifyJsPlugin壓縮代碼,從而生成一個更小的bundle。
// webpack.config.js
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
minimize: true,
},
};
需要注意的是,只有引入ES6 module的代碼才能啟用tree-shaking。對於CommonJS或AMD模塊化的代碼,由於不帶有靜態分析的特性,無法利用tree-shaking功能。
四、treeshaking怎麼讀
對於英文不太好的開發者來說,”tree-shaking”這個詞還是挺難理解的。它到底是什麼意思呢?
實際上,tree-shaking這個詞的意思可以通過拆分詞彙來理解。Tree是樹的意思,是一種數據結構。Shake是搖動的意思,可以引申為「震動」。因此,treeshaking可以理解為「震動樹」(搖動樹的果實掉落下來的意思)。
五、treeshaking不生效
雖然tree-shaking看上去很美好,但實際上開發者們會發現有些時候它並不會生效。有以下一些情況可能導致tree-shaking不生效。
- 在代碼中使用了process.env.NODE_ENV變量,會導致webpack將整個模塊打包進去。
- 有些庫會使用類似於全局註冊的方式註冊組件,比如Ant Design Vue的組件,這會導致tree-shaking失效,因為在編譯時無法知道哪些組件被使用。
- 使用動態導入(如import())時,由於要在運行時決定使用哪個模塊,編譯時不會對這部分代碼進行分析。
- 代碼中使用了webpack的require.ensure()或require.include()等動態加載模塊的方式。
需要注意的是,儘管使用tree-shaking會減小bundle的大小,但並不一定會提升應用程序的性能。這是因為雖然tree-shaking會減小bundle的大小,但整個應用程序的總體積可能並沒有得到明顯的減少,因為一些庫的體積可能還是非常大。
六、treeshaking副作用
雖然tree-shaking在很多情況下可以減小bundle的大小,但使用不當也會帶來一些副作用。
- 可讀性差。優化過度的代碼可能會失去可讀性,這會給維護和代碼優化帶來困難。
- 可能會破壞代碼的正確性。對一些代碼進行tree-shaking可能會破壞代碼的正確性,導致應用程序無法正常運行。
- 代碼冗餘。有時候對代碼進行tree-shaking會導致生成更多的代碼,這可能會導致bundle的大小反而更大。
七、treeshaking對怎樣的包不生效
treeshaking並不是萬能的,對某些類型的包並不會起作用。比如:
- 對於只有一個入口文件的包或庫,tree-shaking會對整個文件進行編譯,而不是只編譯其中被使用的部分。
- 對於內置模塊(比如fs、http等),由於它們沒有使用ES6的模塊化規範,所以tree-shaking並不會起作用。
最後,需要注意一點的是,雖然tree-shaking非常方便,但也不是解決所有性能問題的銀彈。代碼優化應該是一個綜合性的過程,需要綜合考慮代碼的質量、代碼的體積、代碼的可讀性以及代碼的運行效率等多個方面。
完整代碼示例
// index.js
import { sum } from './math';
console.log(sum(1, 2));
// math.js
export function sum(a, b) {
return a + b;
}
export function minus(a, b) {
return a - b;
}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/159008.html