亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

webpack源碼分析之一:文件打包

Richard_Gao / 2116人閱讀

摘要:當(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

相關(guān)文章

  • 模仿webpack實(shí)現(xiàn)簡單的打包工具

    摘要:模仿實(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ā)人員必備的技能之...

    wow_worktile 評(píng)論0 收藏0
  • 模仿webpack實(shí)現(xiàn)簡單的打包工具

    摘要:模仿實(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ā)人員必備的技能之...

    linkFly 評(píng)論0 收藏0
  • 模仿webpack實(shí)現(xiàn)簡單的打包工具

    摘要:模仿實(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ā)人員必備的技能之...

    Simon 評(píng)論0 收藏0
  • webpack4.x 模塊化淺析-CommonJS

    摘要:先看下官方文檔中對(duì)模塊的描述在模塊化編程中,開發(fā)者將程序分解成離散功能塊,并稱之為模塊。每個(gè)模塊具有比完整程序更小的接觸面,使得校驗(yàn)調(diào)試測試輕而易舉。 先看下webpack官方文檔中對(duì)模塊的描述: 在模塊化編程中,開發(fā)者將程序分解成離散功能塊(discrete chunks of functionality),并稱之為模塊。每個(gè)模塊具有比完整程序更小的接觸面,使得校驗(yàn)、調(diào)試、測試輕而易...

    alphahans 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<