成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

Richard_Gao / 2068人閱讀

摘要:當發(fā)現(xiàn)該路徑為文件夾時則,則依次查找如下文件字段擴展名文件解析文件可以定位之后,則是解析定位下來的文件了,本文用的是,文檔如規(guī)范文檔解析文件返回一個語法樹。對語法樹進行遍歷對遇到為且其為為的節(jié)點將該節(jié)點的以及下標包裝成對象儲存起來。

前言

自動化打包工具webpack,相信很多人和我一樣嘗試著研究下它,但是繁雜的功能以及高度抽象的代碼實在是很難理解,所以筆者只能通過github的webpack的第一次提交進行分析,實現(xiàn),并將實現(xiàn)的一些心得分享一下。

功能分析

對于node端來講,有commonjs來規(guī)范模塊的標識,定義,引用。而瀏覽器端由于缺乏原生對象支持就需要通過自我實現(xiàn)來模擬commonjs規(guī)范。
webpack是通過一個IIFE立即調(diào)用函數(shù)表達式去實現(xiàn)這個規(guī)范的。簡要的去注釋,去除內(nèi)部運行的代碼,其格式如下:

(function(module){})([function(){},function(){}]);

簡單點說就是各個模塊代碼以數(shù)組的形式傳遞給運行函數(shù),在進行存儲。詳細分析可以參考簡要分析webpack打包后代碼

所以實現(xiàn)以上的功能需求點如下:

文件路徑分析與定位resolve

文件編譯&解析,分析出依賴文件parse

生成需要打包的文件樹depTree

將依賴文件寫入輸出文件內(nèi)writeChunk

文件分析與定位

本功能和node的require類似,故有參考node require源碼

文件分析,將文件為兩種類型

以 "./","../","/" 標識符開頭的路徑文件模塊

該類文件會通過path.join 轉(zhuǎn)化為真實的路徑而定位。

自定義的文件模塊

這類相對比較麻煩,他在當前目錄下面的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" ]

文件定位

對于部分文件并沒有帶擴展名,此時有默認的擴展名依次以.js,.jsx為后綴依次補充。當然我們可以用傳入extensions,修改默認的擴展名。

{extensions:["js","jsx","jpg"]}

當發(fā)現(xiàn)該路徑為文件夾時則,則依次查找如下文件

package.json(main字段)

index+(擴展名)

文件解析

文件可以定位之后,則是解析定位下來的文件了,本文用的是exprima,文檔如parser規(guī)范文檔

esprima解析文件,返回一個語法樹。

對語法樹進行遍歷,對遇到type 為CallExpression,且其callee為name為require的節(jié)點,將該節(jié)點的value,以及下標包裝成對象儲存起來。

比如

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組成一個可操作的扁平化的對象和存儲著name與id對應(yīng)的map對象。

實現(xiàn)手法上也是遞歸resolve函數(shù),獲取到各個文件的依賴,文件,id的信息,最后得到depTree對象

舉個例子:

{ 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ù)。這塊會用到之前的path和id關(guān)系的map對象,通過路口文件的絕對路徑,找出入口文件的mainId,并進行替換。

寫入?yún)?shù)數(shù)組。遍歷文件樹,將文件節(jié)點的source內(nèi)容替換掉

大致如下:

require("module") 替換為__webpack_require__(0)

這個地方要考慮的點是

如果用replace替換的話,會影響source帶部分關(guān)鍵字的內(nèi)容,不可取。

用索引替換的字符串的話,一旦第一個替換成功,整個字符串長度發(fā)生變化,原先的索引下標就失效了。

官方實現(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))
    });
代碼實現(xiàn)

本人的簡易版webpack實現(xiàn)simple-webpack

(完)

參考資料

webpack早期源碼

require源碼解讀

node require源碼

parser規(guī)范文檔

簡要分析webpack打包后代碼

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107753.html

相關(guān)文章

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

    摘要:模仿實現(xiàn)簡單的打包工具是一款前端項目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,已經(jīng)成為前端開發(fā)人員必備的技能之一,很多開發(fā)人員開始使用和的時候,都會使用默認的單頁應(yīng)該創(chuàng)建指令來創(chuàng)建一個工程化項目,實際上,這些工程化的項目都是基于來搭建的當我們熟悉使 模仿webpack實現(xiàn)簡單的打包工具 webpack是一款前端項目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,webpack已經(jīng)成為前端開發(fā)人員必備的技能之...

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

    摘要:模仿實現(xiàn)簡單的打包工具是一款前端項目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,已經(jīng)成為前端開發(fā)人員必備的技能之一,很多開發(fā)人員開始使用和的時候,都會使用默認的單頁應(yīng)該創(chuàng)建指令來創(chuàng)建一個工程化項目,實際上,這些工程化的項目都是基于來搭建的當我們熟悉使 模仿webpack實現(xiàn)簡單的打包工具 webpack是一款前端項目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,webpack已經(jīng)成為前端開發(fā)人員必備的技能之...

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

    摘要:模仿實現(xiàn)簡單的打包工具是一款前端項目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,已經(jīng)成為前端開發(fā)人員必備的技能之一,很多開發(fā)人員開始使用和的時候,都會使用默認的單頁應(yīng)該創(chuàng)建指令來創(chuàng)建一個工程化項目,實際上,這些工程化的項目都是基于來搭建的當我們熟悉使 模仿webpack實現(xiàn)簡單的打包工具 webpack是一款前端項目構(gòu)建工具,隨著現(xiàn)在前端生態(tài)的發(fā)展,webpack已經(jīng)成為前端開發(fā)人員必備的技能之...

    Simon 評論0 收藏0
  • webpack4.x 模塊化淺析-CommonJS

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

    alphahans 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<