前端技術發展太快,感受一天不努力就要被超越。這不, 最近在寫Angular2練習項目的時候,遇到了一個性能優化的技術點,叫作Tree Shaking。因而,我愉快地開始了學習之旅。 javascript
從技術實現上來講,它是依託於ES6提供的模塊系統對代碼進行靜態分析,並將代碼中的死代碼(dead code)移除的一種技術。所以,利用Tree Shaking技術能夠很方便地實現咱們代碼上的優化,減小代碼體積。前端
隨着ES6在項目中運用的愈來愈普遍,不少人都已經開始使用ES6自帶的模塊系統進行編程。如今你們寫稍微複雜一點的前端項目的時候,一般都會引入多個模塊,如jquery、lodash等等。而這些第三方庫中的不少功能其實可能只會用到一小部分。若是按照傳統的打包方式進行打包的話,你最終的代碼中將會有不少的冗餘代碼,有損前端性能。因而,Tree Shaking應運而生。java
Tree Shaking,從這個技術的命名十分形象,直譯過來就是「搖樹」的意思。在去除代碼冗餘的過程當中,程序會從入口文件出發掃描全部的模塊依賴,以及模塊的子依賴,而後將它們連接起來造成一個「抽象語法樹」(AST)。隨後,運行全部代碼,查看哪些代碼是用到過的,作好標記。最後,再將「抽象語法樹」中沒有用到的代碼「搖落」。這樣一個過程後,就去除了沒有用到的代碼。node
提到Tree Shaking, 就不得不談一下Rollup這個庫了。Tree Shaking這個術語其實就是它命名出來的。Rollup
號稱是下一代ES6的模塊化工具。它支持將用ES6模塊化系統寫的代碼打包成CMD,AMD和IFEE等多種風格的模塊,從而讓瀏覽器或node能更好地支持。而且,在打包過程當中,會使用Tree Shaking技術分析代碼依賴,移除冗餘代碼。接下來我將針對Rollup
這個庫,來說解一下在項目實踐當中它的應用。jquery
你用常見的npm或者目前比較流行的yarn均可以進行安裝:webpack
npm install --save-dev rollup
//or
yarn add rollup --dev複製代碼
Rollup的配置文件相對來講是比較簡單的,對於基礎的打包工做,只要指定文件路口、出口以及打包的格式以後就能夠了。git
先建立一個名爲rollup.config.js
的配置文件:github
export default {
entry: 'app.js',
dest: 'bundle.min.js',
//打包格式
format: 'umd',
sourceMap: false,
}複製代碼
而後執行命令:web
rollup -c rollup.config.js複製代碼
最後將會把app.js
打包成bundle.min.js
的文件。npm
Rollup官方提供了多種插件,能夠實現不少個性化的需求。如:咱們但願在去除代碼冗餘後,再使用uglify對代碼進行壓縮,可使用rollup-plugin-uglify
插件:
import uglify from 'rollup-plugin-uglify';
export default {
....
plugins: [
uglify()
]
}複製代碼
目前Webpack 2.0也已經開始支持Tree Shaking技術,若是須要在打包發佈前用上Tree Shaking,沒必要再額外引入Rollup庫了。要在webpack中使用,以前可能還會用到babel-preset-es2015-native-modules模塊,可是如今只要在.babelrc
文件中作出以下配置:
presets: [["es2015", { "modules": false }]]複製代碼
就能夠了,是否是很簡單呢?
另外,在個人學習過程當中,曾經有一個疑問:現在Webpack已經集成了Tree Shaking,那麼是否還有必要去使用Rollup呢?直到我讀到了這篇文章:Webpack and Rollup: the same but different。引用文章中的一句總結:
Use webpack for apps, and Rollup for libraries
Webpack和Rollup的使用場景其實不太同樣。Webpack功能十分強大,主要用於解決開發複雜SPA應用時面臨的許多問題:如代碼分離(code splitting)、靜態資源引用、模塊按需加載等。但對於Rollup來講,它則更加輕量級,主要是用來構建可以被開發者普遍使用的第三方JS庫的。
目前針對ES6的Tree Shaking技術,還不是特別成熟。特別是你須要處理的代碼會產生反作用的時候,會致使Tree Shaking並不能很好地去除冗餘。所以在具體的項目開發過程中,仍是建議提升代碼編寫的質量,減小冗餘。例如利用一些工具,如eslint,jslint之類的檢查策略,來刪除一些沒有用到的業務代碼。另外一方面,咱們在項目中也能夠採用一些進行優化過的第三方庫。最後,靜態導入包的過程,直接導入子模塊,會比導入整個第三方庫來得更合適,如:
import { map } from 'lodash/fp';
//BAD!
import { map } from 'lodash';複製代碼
做爲dead code elimination的一種方式,Tree Shaking目前已經集成在不少打包工具中了,你們也不妨一試。