摘要:當(dāng)發(fā)現(xiàn)該路徑為文件夾時(shí)則,則依次查找如下文件字段擴(kuò)展名文件解析文件可以定位之后,則是解析定位下來的文件了,本文用的是,文檔如規(guī)范文檔解析文件返回一個(gè)語法樹。對(duì)語法樹進(jìn)行遍歷對(duì)遇到為且其為為的節(jié)點(diǎn)將該節(jié)點(diǎn)的以及下標(biāo)包裝成對(duì)象儲(chǔ)存起來。
前言
自動(dòng)化打包工具webpack,相信很多人和我一樣嘗試著研究下它,但是繁雜的功能以及高度抽象的代碼實(shí)在是很難理解,所以筆者只能通過github的webpack的第一次提交進(jìn)行分析,實(shí)現(xiàn),并將實(shí)現(xiàn)的一些心得分享一下。
功能分析對(duì)于node端來講,有commonjs來規(guī)范模塊的標(biāo)識(shí),定義,引用。而瀏覽器端由于缺乏原生對(duì)象支持就需要通過自我實(shí)現(xiàn)來模擬commonjs規(guī)范。
webpack是通過一個(gè)IIFE立即調(diào)用函數(shù)表達(dá)式去實(shí)現(xiàn)這個(gè)規(guī)范的。簡要的去注釋,去除內(nèi)部運(yùn)行的代碼,其格式如下:
(function(module){})([function(){},function(){}]);
簡單點(diǎn)說就是各個(gè)模塊代碼以數(shù)組的形式傳遞給運(yùn)行函數(shù),在進(jìn)行存儲(chǔ)。詳細(xì)分析可以參考簡要分析webpack打包后代碼
所以實(shí)現(xiàn)以上的功能需求點(diǎn)如下:
文件路徑分析與定位resolve
文件編譯&解析,分析出依賴文件parse
生成需要打包的文件樹depTree
將依賴文件寫入輸出文件內(nèi)writeChunk
文件分析與定位本功能和node的require類似,故有參考node require源碼
文件分析,將文件為兩種類型
以 "./","../","/" 標(biāo)識(shí)符開頭的路徑文件模塊
該類文件會(huì)通過path.join 轉(zhuǎn)化為真實(shí)的路徑而定位。
自定義的文件模塊
這類相對(duì)比較麻煩,他在當(dāng)前目錄下面的node_modules,查找文件,未找到則一路向上查找,最終查找到或者拋出異常。如:
[ "/Users/zhujian/Documents/workspace/webpack/simple-webpack/node_modules", "/Users/zhujian/Documents/workspace/webpack/node_modules", "/Users/zhujian/Documents/workspace/node_modules", "/Users/zhujian/Documents/node_modules", "/Users/zhujian/node_modules", "/Users/node_modules", "/node_modules" ]
文件定位
對(duì)于部分文件并沒有帶擴(kuò)展名,此時(shí)有默認(rèn)的擴(kuò)展名依次以.js,.jsx為后綴依次補(bǔ)充。當(dāng)然我們可以用傳入extensions,修改默認(rèn)的擴(kuò)展名。
{extensions:["js","jsx","jpg"]}
當(dāng)發(fā)現(xiàn)該路徑為文件夾時(shí)則,則依次查找如下文件
package.json(main字段)
index+(擴(kuò)展名)
文件解析
文件可以定位之后,則是解析定位下來的文件了,本文用的是exprima,文檔如parser規(guī)范文檔
esprima解析文件,返回一個(gè)語法樹。
對(duì)語法樹進(jìn)行遍歷,對(duì)遇到type 為CallExpression,且其callee為name為require的節(jié)點(diǎn),將該節(jié)點(diǎn)的value,以及下標(biāo)包裝成對(duì)象儲(chǔ)存起來。
比如
const b = require("./b");
解析后
.... "init": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "require", "range": [ 10, 17 ] }, "arguments": [ { "type": "Literal", "value": "./b", "raw": ""./b"", "range": [ 18, 23 ] } ], "range": [ 10, 24 ] }, ....
我們要做的就是提取value "./b",以及該字符串在文件所處的位置range。
文件樹生成主要是從入口文件開始,將所有依賴的js,以及其內(nèi)容,分配的id組成一個(gè)可操作的扁平化的對(duì)象和存儲(chǔ)著name與id對(duì)應(yīng)的map對(duì)象。
實(shí)現(xiàn)手法上也是遞歸resolve函數(shù),獲取到各個(gè)文件的依賴,文件,id的信息,最后得到depTree對(duì)象
舉個(gè)例子:
{ modules: { "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/a.js": { filename: "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/a.js", id: 0, requires: [Array], rangeRequires: [Array], source: "const b = require("./b"); const c = require("c"); const {e, f, g} = require("./m"); }, "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/b.js": { filename: "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/b.js", id: 1, requires: [], rangeRequires: [], source: "const b = "b"; module.exports = b; " }, "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/node_modules/c.js": { filename: "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/node_modules/c.js", id: 2, requires: [], rangeRequires: [], source: "const c = "c"; module.exports = c; " }, "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/m.js": { filename: "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/m.js", id: 3, requires: [], rangeRequires: [], source: "http:// const core = require("./core"); const a = 1; }, nextModuleId: 4, mapNameToId: { "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/a.js": 0, "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/b.js": 1, "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/node_modules/c.js": 2, "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/m.js": 3 } }文件寫入
寫入主函數(shù),替換入口的執(zhí)行函數(shù)。這塊會(huì)用到之前的path和id關(guān)系的map對(duì)象,通過路口文件的絕對(duì)路徑,找出入口文件的mainId,并進(jìn)行替換。
寫入?yún)?shù)數(shù)組。遍歷文件樹,將文件節(jié)點(diǎn)的source內(nèi)容替換掉
大致如下:
require("module") 替換為__webpack_require__(0)
這個(gè)地方要考慮的點(diǎn)是
如果用replace替換的話,會(huì)影響source帶部分關(guān)鍵字的內(nèi)容,不可取。
用索引替換的字符串的話,一旦第一個(gè)替換成功,整個(gè)字符串長度發(fā)生變化,原先的索引下標(biāo)就失效了。
官方實(shí)現(xiàn)
const result = [source]; replaces.forEach(replace => { const {from, value, end} = replace; const source = result.shift(); result.unshift(source.substr(0, from), value, source.substr(end)) });代碼實(shí)現(xiàn)
本人的簡易版webpack實(shí)現(xiàn)simple-webpack
(完)
參考資料webpack早期源碼
require源碼解讀
node require源碼
parser規(guī)范文檔
簡要分析webpack打包后代碼
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/107753.html
摘要:模仿實(shí)現(xiàn)簡單的打包工具是一款前端項(xiàng)目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,已經(jīng)成為前端開發(fā)人員必備的技能之一,很多開發(fā)人員開始使用和的時(shí)候,都會(huì)使用默認(rèn)的單頁應(yīng)該創(chuàng)建指令來創(chuàng)建一個(gè)工程化項(xiàng)目,實(shí)際上,這些工程化的項(xiàng)目都是基于來搭建的當(dāng)我們熟悉使 模仿webpack實(shí)現(xiàn)簡單的打包工具 webpack是一款前端項(xiàng)目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,webpack已經(jīng)成為前端開發(fā)人員必備的技能之...
摘要:模仿實(shí)現(xiàn)簡單的打包工具是一款前端項(xiàng)目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,已經(jīng)成為前端開發(fā)人員必備的技能之一,很多開發(fā)人員開始使用和的時(shí)候,都會(huì)使用默認(rèn)的單頁應(yīng)該創(chuàng)建指令來創(chuàng)建一個(gè)工程化項(xiàng)目,實(shí)際上,這些工程化的項(xiàng)目都是基于來搭建的當(dāng)我們熟悉使 模仿webpack實(shí)現(xiàn)簡單的打包工具 webpack是一款前端項(xiàng)目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,webpack已經(jīng)成為前端開發(fā)人員必備的技能之...
摘要:模仿實(shí)現(xiàn)簡單的打包工具是一款前端項(xiàng)目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,已經(jīng)成為前端開發(fā)人員必備的技能之一,很多開發(fā)人員開始使用和的時(shí)候,都會(huì)使用默認(rèn)的單頁應(yīng)該創(chuàng)建指令來創(chuàng)建一個(gè)工程化項(xiàng)目,實(shí)際上,這些工程化的項(xiàng)目都是基于來搭建的當(dāng)我們熟悉使 模仿webpack實(shí)現(xiàn)簡單的打包工具 webpack是一款前端項(xiàng)目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,webpack已經(jīng)成為前端開發(fā)人員必備的技能之...
摘要:先看下官方文檔中對(duì)模塊的描述在模塊化編程中,開發(fā)者將程序分解成離散功能塊,并稱之為模塊。每個(gè)模塊具有比完整程序更小的接觸面,使得校驗(yàn)調(diào)試測試輕而易舉。 先看下webpack官方文檔中對(duì)模塊的描述: 在模塊化編程中,開發(fā)者將程序分解成離散功能塊(discrete chunks of functionality),并稱之為模塊。每個(gè)模塊具有比完整程序更小的接觸面,使得校驗(yàn)、調(diào)試、測試輕而易...
閱讀 3075·2021-11-23 09:51
閱讀 2922·2021-11-11 16:55
閱讀 3027·2021-10-14 09:43
閱讀 1464·2021-09-23 11:22
閱讀 1103·2019-08-30 11:04
閱讀 1789·2019-08-29 11:10
閱讀 1023·2019-08-27 10:56
閱讀 3213·2019-08-26 12:01