tree shaking
是一個術語,一般用於描述移除 JavaScript
上下文中的未引用代碼(dead-code
)。它依賴於 ES2015
模塊語法的 靜態結構 特性,例如 import
和 export
。css
這個術語和概念其實是由 ES2015
模塊打包工具 rollup 普及起來的,它是DCE(dead code elimination)
的一個實現,經過tree shaking
的分析,可使你代碼裏沒有使用的代碼所有刪除。然而它又區別於普通的DCE
,它是去找真正使用的代碼,而不是從已有代碼裏刪除代碼。webpack
刪除無用代碼,縮小文件體積,提高加載速度。web
tree shaking
依賴的是ES6 module
。
ES6 module
是編譯時加載,編譯時就能夠肯定模塊的依賴關係,能夠安全地作靜態分析。而且具備如下特性:json
這就是 tree shaking
實現的基礎。先經過import
的引入,靜態分析依賴,而後刪除無用代碼。安全
mode: "production"
模式下,默認打開tree shaking
咱們先看個簡單的例子,純函數:bash
.
├── dist
│ └── main.js
├── package-lock.json
├── package.json
├── src
│ ├── index.js
│ └── util.js
└── webpack.config.js
複製代碼
// util.js
export function a() {
console.log('this is a')
}
export function b() {
console.log('this is b')
}
複製代碼
// index.js
import { a } from './util'
複製代碼
在util.js
定義了兩個方法,可是index.js
只引入了a
,而且沒有調用,咱們的預想是這些都不該該打包進去。webpack-dev-server
a
方法
// index.js
import { a } from './util'
a()
複製代碼
能夠看到a
已經被打包進去了,b
由於沒有被引入調用,因此消除了。 這麼看是否是很easy~ide
咱們再測試一下類的消除函數
// person.js
class Person {
constructor() {}
sayName() {
console.log('I am daly')
}
sayAge() {
console.log('I am 18')
}
}
export default Person
複製代碼
// index.js
import Person from './person'
複製代碼
咱們調用一個方法試試工具
// index.js
import Person from './person'
let somebody = new Person()
somebody.sayName()
複製代碼
咦~我只調用了sayName
,可是打包結果能夠看出,這個類都被打包了。從這咱們能夠看出,類是不能分割打包的,即便方法之間沒有依賴。
到這都只是簡單的例子,看起來使用很簡單,不須要咱們思考,可是呢,去看官方文檔,會發現提到了一個 side effect
反作用的概念。
"side effect(反作用)"
的定義是,在導入時會執行特殊行爲的代碼,而不是僅僅暴露一個export
或多個export
。舉例說明,例如polyfill
,它影響全局做用域,而且一般不提供export
。
我來回讀了幾遍,都以爲它的意思是,有反作用的代碼必定要記得標註在sideEffects
裏,由於所在模塊只引入沒調用的話,生產模式下會被刪掉的,這樣特殊行爲代碼就執行不到了。可是,我發現最新的版本並不是這樣~~~
咱們先理解一下,什麼是有反作用的代碼
// person.js
class Person {
constructor() { }
sayName() {
console.log('I am daly')
}
sayAge() {
console.log('I am 18')
}
}
Array.prototype.testSomething = function () {
console.log('this is side effect')
}
window.test = 'test'
export default Person
複製代碼
除了export
的兩個方法外,我還給Array
對象新增了一個方法,在window
上掛了一個全局變量。 當引入person
文件的時候,即便沒有調用方法,這些方法也會執行的。這就能夠稱之爲反作用。
// index.js
import Person from './person'
複製代碼
那咱們分析下上面的例子,person.js
文件被引入了,可是沒有調用,按照以前的邏輯,是否是應該整個文件都不打包了?這樣是否是就執行不到咱們寫的額外的函數了?
直接打包看一下~
exprot
的特殊行爲代碼段會被打包,可是沒被調用的方法,一個都沒打包進去! 我測試過在
package.json
里加上
sideEffects
參數,打包結果徹底和上圖同樣。
咱們再引入一個css文件試試
// index.css
* {
font-size: 24px;
}
複製代碼
// index.js
import './index.css'
複製代碼
無需把這個文件加入sideEffects
,也會被打包進去。
就是說tree shaking
如今已經十分智能,能夠區分是否爲反作用代碼,實現一個比較理想的優化打包。
可是畢竟是寫在官網上面的文檔,不知道是否是我我的理解有誤,以後須要再多嘗試一下。
webpack學習之路(九)SplitChunksPlugin配置
webpack學習之路(六)hash/chunkHash/contentHash
webpack學習之路(五)loader初識及經常使用loader介紹
webpack學習之路(四)webpack-hot-middleware實現熱更新
webpack學習之路(三)webpack-dev-middleware
webpack學習之路(二)webpack-dev-server實現熱更新
I am moving forward.