今天這道題目是在和小紅書的一位面試官聊的時候:前端
我:若是要你選擇一道題目來考察面試者,你最有可能選擇哪一道?webpack
面試官:那應該就是介紹一下tree shaking
及其工做原理?es6
我:爲何?web
面試官:是由於最近面了好多同窗,你們都說熟悉webpack
,在項目中如何去使用、如何去優化,也都或多或少會提到tree shaking
,可是每當我深刻去問其工做機制或者原理時,卻少有人能回答上來。(小聲 bb:並非我想內卷,確實是工程師的基本素養啊,哈哈 😄)面試
面試官:那你來回答一下這個問題?瀏覽器
我:我也用過tree shaking
,只是知道它的別名叫樹搖
,最先是由Rollup
實現,是一種採用刪除不須要的額外代碼的方式優化代碼體積
的技術。可是關於它的原理,我還真的不知道,額,,,,服務器
咱們平時更多時候是停留在應用層面,這種只是能知足基礎的業務訴求,對於後期的技術深挖以及我的的職業發展都是受限的。仍是那句老話:知其然,更要知其因此然~
話很少說,下面我就帶你們一塊兒來深刻探究這個問題。post
Tree shaking
Tree shaking
是一種經過清除多餘代碼方式來優化項目打包體積的技術,專業術語叫Dead code elimination
這個概念,我相信大多數同窗都是瞭解的。什麼,你不懂?學習
不懂不要緊,我能夠教你啊(不過那是另外的價錢,哈哈 🙈)優化
走遠了,兄弟,讓咱們言歸正傳:tree shaking
如何工做的呢?
tree shaking
如何工做的呢?雖然 tree shaking
的概念在 1990 就提出了,但直到 ES6
的 ES6-style
模塊出現後才真正被利用起來。
在ES6
之前,咱們可使用CommonJS
引入模塊:require()
,這種引入是動態的,也意味着咱們能夠基於條件來導入須要的代碼:
let dynamicModule; // 動態導入 if (condition) { myDynamicModule = require("foo"); } else { myDynamicModule = require("bar"); }
可是CommonJS
規範沒法肯定在實際運行前須要或者不須要某些模塊,因此CommonJS
不適合tree-shaking
機制。在 ES6
中,引入了徹底靜態的導入語法:import
。這也意味着下面的導入是不可行的:
// 不可行,ES6 的import是徹底靜態的 if (condition) { myDynamicModule = require("foo"); } else { myDynamicModule = require("bar"); }
咱們只能經過導入全部的包後再進行條件獲取。以下:
import foo from "foo"; import bar from "bar"; if (condition) { // foo.xxxx } else { // bar.xxx }
ES6
的import
語法能夠完美使用tree shaking
,由於能夠在代碼不運行的狀況下就能分析出不須要的代碼。
看完上面的分析,你可能仍是有點懵,這裏我簡單作下總結:由於tree shaking
只能在靜態modules
下工做。ECMAScript 6
模塊加載是靜態的,所以整個依賴樹能夠被靜態地推導出解析語法樹。因此在 ES6
中使用 tree shaking
是很是容易的。
tree shaking
的原理是什麼?看完上面的分析,相信這裏你能夠很容易的得出題目的答案了:
ES6 Module
引入進行靜態分析,故而編譯的時候正確判斷到底加載了那些模塊但到這裏,本篇文章還沒結束。從這道題目咱們能夠很容易的引伸出來另一道「明星」面試題:common.js 和 es6 中模塊引入的區別?
這道題目來自冴羽
大佬的阿里前端攻城獅們寫了一份前端面試題答案,請查收
這裏就直接貼下他給出的答案了:
CommonJS
是一種模塊規範,最初被應用於 Nodejs
,成爲 Nodejs
的模塊規範。運行在瀏覽器端的 JavaScript
因爲也缺乏相似的規範,在 ES6
出來以前,前端也實現了一套相同的模塊規範 (例如: AMD
),用來對前端模塊進行管理。自 ES6
起,引入了一套新的 ES6 Module
規範,在語言標準的層面上實現了模塊功能,並且實現得至關簡單,有望成爲瀏覽器和服務器通用的模塊解決方案。但目前瀏覽器對 ES6 Module
兼容還不太好,咱們平時在 Webpack
中使用的 export
和 import
,會通過 Babel
轉換爲 CommonJS
規範。在使用上的差異主要有:
一、CommonJS
模塊輸出的是一個值的拷貝,ES6
模塊輸出的是值的引用。
二、CommonJS
模塊是運行時加載,ES6
模塊是編譯時輸出接口。
三、CommonJs
是單個值導出,ES6 Module
能夠導出多個
四、CommonJs
是動態語法能夠寫在判斷裏,ES6 Module
靜態語法只能寫在頂層
五、CommonJs
的 this
是當前模塊,ES6 Module
的 this
是 undefined
冴羽
大佬的文章質量都很是高,也歡迎你們多去支持冴羽
大佬,相信看完必定會對你有所收穫。
這是大廠面試問題解析
的第二篇了,和以前準備寫這一系列的初衷同樣:我力求經過一些面試題去發掘本身不曾瞭解或者不曾深刻了解的一個領域。
面試題更多時候是一個引子,更可能是想經過面試題去思考題目背後帶來的對某一模塊的深刻學習和探討。
固然,每篇文章也不會只是草草給出答案,我都會盡可能深刻淺出的給出本身對於這道題目的理解,也會在這個基礎上作一些拓展。