複習webpack4之實現簡易的webpack

以前學習過webpack3的知識,可是webpack4升級後仍是有不少變更的,因此此次從新整理一下webpack4的知識點,方便之後複習。node

此次學習webpack4不只僅要會配置,記住核心API,最好還要理解一下webpack更深層次的知識,好比打包原理等等,因此可能會省略一些比較基礎的內容,可是但願我能夠經過這次學習掌握webpack,更好地應對之後的工做。webpack

這一節會深刻理解webpack原理git

1.模塊分析

咱們這一次會實現一個相似webpack的工具,首先來寫模塊分析部分。github

代碼地址:web

代碼倉庫npm

先把目錄搭好,src下有三個js文件,每一個文件裏面對應如下內容:數組

word.js瀏覽器

message.jsbash

index.jsbabel

如今這個代碼在瀏覽器中是沒有辦法運行的,須要藉助相似webpack這種工具才能夠,因此咱們須要藉助node.js實現一個打包工具。

和src同級,咱們新建一個bundler.js。

建立一個函數,用來分析打包入口文件,支持傳入一個參數(文件路徑),而後利用node讀取文件內容。

而index中引用了message.js,咱們須要把引用的文件名提取出來,要藉助@babel/parser分析咱們的源代碼。

cnpm install @babel/parser --save
複製代碼

@babel/parser提供了一個parse方法,第一個參數傳入文件內容,第二個參數傳一個對象。

方法返回的對象是一個抽象語法樹(AST)。

對象裏面有一個program.body,內容是這樣的:

第一個Node的type是ImportDeclaration,意思是引入聲明語句,咱們index.js中第一行確實是引入語句。第二個Node的type是ExpressionStatement,意思是表達式語句,咱們第二行寫的console.log(),確實是表達式語句。因此藉助這個工具,咱們就能夠分析文件之間的依賴關係。

爲了找出全部的依賴關係,咱們要遍歷全部type是ImportDeclaration的語句,本身寫會比較麻煩,還能夠藉助@babel/traverse

cnpm install --save @babel/traverse
複製代碼

traverse是一個函數,第一個參數接受抽象語法樹,第二個參數是一個對象。

抽象語法樹中有元素的type是ImportDeclaration時,就會執行ImportDeclaration函數,它接受的參數能夠解構出一個node,它就是全部type是ImportDeclaration的元素,就是咱們全部的依賴,裏面喲一個source,value值就是文件名,因此咱們就能夠把全部文件名都存起來

聲明一個數組,把全部node中的soure.value都push到數組中。

這樣入口分析就已經分析好了,可是這時候分析的依賴都是相對路徑,咱們要把它改成絕對路徑,或者是相對於根路徑的相對路徑,這樣纔不會有問題,因此要藉助node中的path。

可是咱們爲了方便之後開發,如今應該把絕對路徑和相對路徑都存好,因此把原先的數組變成對象,用如下方法存起來。

對象的key是相對路徑,value是絕對路徑。

而後就返回入口文件名,和文件全部依賴的內容。

可是咱們用的ES Module引入文件,瀏覽器沒法識別這個語法,就要依賴@babel/core。

cnpm install --save @babel/core
複製代碼

@babel/core提供了一個方法,transformFromAst,能夠把抽象語法樹轉化成瀏覽器能夠運行的代碼。

傳入的參數中還能夠配置ES6轉ES5的插件,因此要先安裝一下@babel/preset-env。

cnpm install --save @babel/preset-env
複製代碼

函數會返回一個對象,裏面有一個code屬性,code屬性中就是咱們瀏覽器能夠運行的代碼。

最後返回咱們分析的結果。

返回的結果意思是:入口文件是index.js;引用的依賴是message.js,地址是src/message.js;瀏覽器中能夠運行的代碼是code中的內容。

2.依賴圖譜

咱們如今只分析了入口文件的依賴,接下來咱們要開始分析其餘依賴,從message開始,一層一層把全部依賴都分析完。

咱們再建立一個函數,用來製做依賴圖譜,利用相似遞歸的方式,調用moduleAnalyser逐層分析依賴內容,並把它們都放到一個數組中。

最後生成的數組。

而後咱們把它整合成一個對象,用路徑做爲key,依賴和代碼做爲value,而且返回這個對象。

對象的內容。

3.生成代碼

拿到依賴圖譜,如今要開始生成瀏覽器能夠運行的代碼了。

先看生成的代碼中,存在require和exports兩個方法,可是瀏覽器中沒有這兩個方法,因此咱們要先定義這兩個方法,而後把生成的代碼片斷利用閉包的形式執行。

require函數中,經過傳入路徑拿到對應的代碼,利用eval()執行,若是require中有依賴,繼續執行require時拿到的就是相對路徑,須要轉成絕對路徑,直接去咱們以前建立的對象中取就能夠。

exports是一個空對象便可,這樣導出的內容會被存到exports中。

而後把生成的代碼格式化一下,複製到瀏覽器中執行。

就打印出say hello了。

這樣,咱們就已經實現了一個簡易的webpack打包工具了,具體代碼能夠去個人github倉庫裏面看。

參考

從基礎到實戰 手把手帶你掌握新版Webpack4.0 ----DellLee
相關文章
相關標籤/搜索