复习webpack4之实现简易的webpack
之前學習過webpack3的知識,但是webpack4升級后還是有很多變動的,所以這次重新整理一下webpack4的知識點,方便以后復習。
這次學習webpack4不僅僅要會配置,記住核心API,最好還要理解一下webpack更深層次的知識,比如打包原理等等,所以可能會省略一些比較基礎的內容,但是希望我可以通過此次學習掌握webpack,更好地應對以后的工作。
這一節會深入理解webpack原理
1.模塊分析
我們這一次會實現一個類似webpack的工具,首先來寫模塊分析部分。
代碼地址:
代碼倉庫
先把目錄搭好,src下有三個js文件,每個文件里面對應以下內容:
word.js
message.js
index.js
現在這個代碼在瀏覽器中是沒有辦法運行的,需要借助類似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轉載于:https://juejin.im/post/5d00fbbb5188255e780b64b1
總結
以上是生活随笔為你收集整理的复习webpack4之实现简易的webpack的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL 时间处理
- 下一篇: 剑指Offer 56 数组中数字出现的次