成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

只用90行代碼實現模塊打包器

開發 前端
今天來聊聊如何用90行代碼實現一個現代JS模塊打包器。我們的打包器雖然迷你,但是實現了webpack的核心功能。而且,我知道你看到大段代碼頭疼,所以這篇文章都是圖。

[[422769]]

大家好,我卡頌。

今天來聊聊如何用90行代碼實現一個現代JS模塊打包器。

我們的打包器雖然迷你,但是實現了webpack的核心功能。

而且,我知道你看到大段代碼頭疼,所以這篇文章都是圖。看完感興趣的話,這里是完整代碼的倉庫地址[1],只有90行代碼哦。

讓我們愉快的開始吧。

生成依賴圖

如果應用是個毛線團的話,那么入口文件就是線頭。打包器要做的第一件事是:

順著線頭開始濾清整條線的走向

[[422770]]

假設入口文件是entry.js:

  1. // entry.js 
  2.  
  3. import a from './a.js'
  4. import b from './b.js'
  5.  
  6. console.log(a, b); 

他依賴了a.js與b.js。 


em... 有點太簡陋了,讓我們再擴展下a.js與b.js:

  1. // a.js 
  2. import c from './c.js'
  3.  
  4. // ... 
  1. // b.js 
  2. import d from './d.js'
  3. import e from './e.js'
  4.  
  5. // ... 

所以整個依賴關系是這樣:

打包器會從入口文件開始,嘗試建立模塊(即js文件)間的依賴關系,也就是剛才我們講的「順著線頭開始濾清整條線的走向」。

模塊間的依賴關系可以通過分析模塊代碼中的import 聲明語句得知。

為了能分析import 聲明語句,可以使用babel等編譯工具將模塊代碼分解為AST(抽象語法樹)。

遍歷AST,類型為ImportDeclaration的節點就是import聲明語句。

最后,我們將AST重新轉換為可執行的目標代碼,可能還需要根據代碼要執行的宿主環境(一般為瀏覽器)對代碼做一些轉換。

比如,瀏覽器不支持import './a.js'這樣的ESM語法,那么我們需要將所有ESM語法轉為CJS語法。

  1. // 源代碼 
  2. import './a.js'
  3.  
  4. // 轉換后 
  5. require('./a.js'); 

所以,對于任一模塊(js文件),會經歷:

右邊包含目標代碼和模塊間依賴關系的數據結構被稱為asset。

每個asset可以通過模塊間依賴關系找到依賴的模塊,重復這一過程,生成新的asset,最終形成整個應用所有asset間的依賴關系:

應用完整的依賴關系被稱為「依賴圖」(dependency graph)。

打包代碼

接下來,只需要遍歷「依賴圖」,將所有asset的目標代碼打包在一起就行。

所有代碼會被打包在一個「立即執行函數」中:

  1. (function(modules) { 
  2.   // 打包好的代碼 
  3. })(modules) 

modules中保存了所有asset及他們之間的依賴關系。

如果你對modules的細節感興趣,可以去文末倉庫里翻代碼

剛才說過,asset的目標代碼是CJS規范的,類似:

  1. // entry.js 
  2.  
  3. require('./a.js'); 
  4. require('./b.js'); 

這意味著我們需要實現:

  • require方法(用于引入依賴的其他asset的目標代碼)
  • module對象(用于保存當前asset的目標代碼執行后導出的數據)

同時,為了防止不同asset的目標代碼中的變量互相污染,每個目標代碼需要獨立的作用域。

我們將目標代碼包裹在函數中:

  1. // 我們操作的是字符串模版 
  2. `function (require, module, exports) { 
  3.   ${asset.code} 
  4. }` 

所以,最終打包的結果為:

  1. (function(modules) { 
  2.   function require() {// ...} 
  3.    
  4.   require(入口asset的ID) 
  5. })(modules) 

這段字符串被包裹在瀏覽器  

這段字符串被包裹在瀏覽器<script>標簽內,會依次執行:

  1. require(入口asset的ID),執行入口asset的目標代碼
  2. 目標代碼內部會調用require執行其他asset的目標代碼
  3. 一步步執行下去...

總結

打包器的工作原理分為兩步:

  1. 從入口文件開始遍歷,生成「依賴圖」
  2. 根據依賴圖,將代碼打包進一個「立即執行函數」

這個打包器還很稚嫩,缺失很多必要的功能,比如:

  • 解決循環依賴
  • 緩存

但是瑕不掩瑜嘛~

參考資料

[1]完整代碼的倉庫地址: https://github.com/BetaSu/minipack

 

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2014-06-19 10:02:32

Haskell代碼

2019-11-15 15:50:41

JS代碼React前端

2021-03-08 15:04:48

編程Python代碼

2020-04-02 15:39:51

代碼編譯器前端

2019-06-05 15:00:28

Java代碼區塊鏈

2022-06-29 09:02:31

go腳本解釋器

2019-12-03 08:29:39

代碼調優網絡

2018-08-02 17:39:42

iPhone備忘錄iOS

2022-06-28 08:17:10

JSON性能反射

2022-03-26 22:28:06

加密通信Python

2022-04-09 09:11:33

Python

2020-12-17 08:06:33

CSS 日歷界面

2018-01-23 09:17:22

Python人臉識別

2025-03-25 08:15:00

JavaScript開發代碼

2018-01-05 14:48:03

前端JavaScript富文本編輯器

2022-04-15 08:07:21

ReactDiff算法

2021-12-16 06:21:16

React組件前端

2020-08-19 10:30:25

代碼Python多線程

2022-02-08 12:30:30

React事件系統React事件系統

2021-09-09 06:55:43

Web剪輯視頻
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久99精品久久久久久国产越南 | 亚洲精品视频免费观看 | 久久专区| 国产精品久久国产精品 | 成人综合视频在线观看 | 福利一区二区 | 久久久久国产一区二区三区 | 精品福利一区二区三区 | 视频一区在线 | 国产高潮av | 色综久久 | h视频在线免费看 | 91毛片在线看| 欧美激情综合色综合啪啪五月 | 久久亚洲一区 | 成人激情视频免费在线观看 | 91麻豆产精品久久久久久夏晴子 | 午夜日韩 | 午夜免费小视频 | 91色视频在线观看 | 免费观看一级特黄欧美大片 | 一区二区在线免费播放 | 91在线精品一区二区 | 日本久久久久久久久 | 午夜激情在线 | 香蕉av免费 | 久久精品中文 | av大片| 亚洲二区在线观看 | 国内精品久久久久久久 | 日韩一二三 | 成人高清网站 | 亚洲午夜小视频 | 美女爽到呻吟久久久久 | 日朝毛片| 欧美激情一区二区 | 综合久久av | 亚洲精品欧美精品 | 国产精品色哟哟网站 | 久久久蜜桃一区二区人 | 手机在线观看 |