小紅書面試官:介紹一下 tree shaking 及其工做原理

寫在前面

今天這道題目是在和小紅書的一位面試官聊的時候:前端

我:若是要你選擇一道題目來考察面試者,你最有可能選擇哪一道?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 就提出了,但直到 ES6ES6-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
}

ES6import語法能夠完美使用tree shaking,由於能夠在代碼不運行的狀況下就能分析出不須要的代碼。

看完上面的分析,你可能仍是有點懵,這裏我簡單作下總結:由於tree shaking只能在靜態modules下工做。ECMAScript 6 模塊加載是靜態的,所以整個依賴樹能夠被靜態地推導出解析語法樹。因此在 ES6 中使用 tree shaking 是很是容易的。

tree shaking的原理是什麼?

看完上面的分析,相信這裏你能夠很容易的得出題目的答案了:

  • ES6 Module引入進行靜態分析,故而編譯的時候正確判斷到底加載了那些模塊
  • 靜態分析程序流,判斷那些模塊和變量未被使用或者引用,進而刪除對應代碼

common.js 和 es6 中模塊引入的區別?

但到這裏,本篇文章還沒結束。從這道題目咱們能夠很容易的引伸出來另一道「明星」面試題:common.js 和 es6 中模塊引入的區別?

這道題目來自冴羽大佬的阿里前端攻城獅們寫了一份前端面試題答案,請查收

這裏就直接貼下他給出的答案了:

CommonJS 是一種模塊規範,最初被應用於 Nodejs,成爲 Nodejs 的模塊規範。運行在瀏覽器端的 JavaScript 因爲也缺乏相似的規範,在 ES6 出來以前,前端也實現了一套相同的模塊規範 (例如: AMD),用來對前端模塊進行管理。自 ES6 起,引入了一套新的 ES6 Module 規範,在語言標準的層面上實現了模塊功能,並且實現得至關簡單,有望成爲瀏覽器和服務器通用的模塊解決方案。但目前瀏覽器對 ES6 Module 兼容還不太好,咱們平時在 Webpack 中使用的 exportimport,會通過 Babel 轉換爲 CommonJS 規範。在使用上的差異主要有:

一、CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用。

二、CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。

三、CommonJs 是單個值導出,ES6 Module能夠導出多個

四、CommonJs 是動態語法能夠寫在判斷裏,ES6 Module 靜態語法只能寫在頂層

五、CommonJsthis 是當前模塊,ES6 Modulethisundefined

冴羽大佬的文章質量都很是高,也歡迎你們多去支持冴羽大佬,相信看完必定會對你有所收穫。

總結一下

這是大廠面試問題解析的第二篇了,和以前準備寫這一系列的初衷同樣:我力求經過一些面試題去發掘本身不曾瞭解或者不曾深刻了解的一個領域。

面試題更多時候是一個引子,更可能是想經過面試題去思考題目背後帶來的對某一模塊的深刻學習和探討。

固然,每篇文章也不會只是草草給出答案,我都會盡可能深刻淺出的給出本身對於這道題目的理解,也會在這個基礎上作一些拓展。

相關文章
相關標籤/搜索