亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何實(shí)現(xiàn)一個(gè)webpack模塊解析器

 更新時(shí)間:2018年10月24日 14:21:46   作者:yhlben  
這篇文章主要介紹了如何實(shí)現(xiàn)一個(gè)webpack模塊解析器,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

最近在學(xué)習(xí) webpack源碼,由于源碼比較復(fù)雜,就先梳理了一下整體流程,就參考官網(wǎng)的例子,手寫一個(gè)最基本的 webpack 模塊解析器。

代碼很少,github地址:手寫webpack模塊解析器

整體流程分析

1、讀取入口文件。

2、將內(nèi)容轉(zhuǎn)換成 ast 語(yǔ)法樹。

3、深度遍歷語(yǔ)法樹,找到所有的依賴,并加入到一個(gè)數(shù)組中。

4、將 ast 代碼轉(zhuǎn)換回可執(zhí)行的 js 代碼。

5、編寫 require 函數(shù),根據(jù)入口文件,自動(dòng)執(zhí)行完所有的依賴。

6、輸出運(yùn)行結(jié)果。

createAsset

// 讀取內(nèi)容并提取它的依賴關(guān)系
function createAsset(filename) {
 // 以字符串的形式讀取文件
 const content = fs.readFileSync(filename, "utf-8");

 // 轉(zhuǎn)換字符串為ast抽象語(yǔ)法樹
 const ast = babylon.parse(content, {
  sourceType: "module"
 });

 const dependencies = [];

 // 遍歷抽象語(yǔ)法樹
 traverse(ast, {
  // 每當(dāng)遍歷到import語(yǔ)法的時(shí)候
  ImportDeclaration: ({ node }) => {
   // 把依賴的模塊加入到數(shù)組中
   dependencies.push(node.source.value);
  }
 });

 const id = ID++;

 // 轉(zhuǎn)換為瀏覽器可運(yùn)行的代碼
 const { code } = babel.transformFromAstSync(ast, null, {
  presets: ["@babel/preset-env"]
 });

 return {
  id,
  filename,
  dependencies,
  code
 };
}

createGraph

// 從入口開始,分析所有依賴項(xiàng),形成依賴圖,采用深度優(yōu)先遍歷
function createGraph(entry) {
 const mainAsset = createAsset(entry);

 // 定義一個(gè)保存依賴項(xiàng)的數(shù)組
 const queue = [mainAsset];

 for (const asset of queue) {
  const dirname = path.dirname(asset.filename);

  // 定義一個(gè)保存子依賴項(xiàng)的屬性
  asset.mapping = {};

  asset.dependencies.forEach(relativePath => {
   const absolutePath = path.join(dirname, relativePath);

   const child = createAsset(absolutePath);

   // 給子依賴項(xiàng)賦值
   asset.mapping[relativePath] = child.id;

   // 將子依賴也加入隊(duì)列中,循環(huán)處理
   queue.push(child);
  });
 }
 return queue;
}

bundle

// 根據(jù)生成的依賴關(guān)系圖,生成瀏覽器可執(zhí)行文件
function bundle(graph) {
 let modules = "";

 // 把每個(gè)模塊中的代碼放在一個(gè)function作用域內(nèi)
 graph.forEach(mod => {
  modules += `${mod.id}:[
   function (require, module, exports){
    ${mod.code}
   },
   ${JSON.stringify(mod.mapping)},
  ],`;
 });

 // require, module, exports 不能直接在瀏覽器中使用,這里模擬了模塊加載,執(zhí)行,導(dǎo)出操作。
 const result = `
  (function(modules){
   // 創(chuàng)建一個(gè)require()函數(shù): 它接受一個(gè) 模塊ID 并在我們之前構(gòu)建的模塊對(duì)象查找它.
   function require(id){
    const [fn, mapping] = modules[id];

    function localRequire(relativePath){
     // 根據(jù)mapping的路徑,找到對(duì)應(yīng)的模塊id
     return require(mapping[relativePath]);
    }

    const module = {exports:{}};

    // 執(zhí)行轉(zhuǎn)換后的代碼,并輸出內(nèi)容。
    fn(localRequire,module,module.exports);

    return module.exports;
   }

   // 執(zhí)行入口文件
   require(0);

  })({${modules}})
 `;

 return result;
}

執(zhí)行解析

const graph = createGraph("./entry.js");
const result = bundle(graph);

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JavaScript中數(shù)組去重的5種方法

    JavaScript中數(shù)組去重的5種方法

    這篇文章主要介紹了JavaScript中數(shù)組去重的5種方法,文中講解非常詳細(xì),實(shí)例代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 淺析微信小程序自定義日歷組件及flex布局最后一行對(duì)齊問(wèn)題

    淺析微信小程序自定義日歷組件及flex布局最后一行對(duì)齊問(wèn)題

    這篇文章主要介紹了微信小程序自定義日歷組件及flex布局最后一行對(duì)齊問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • uni-app多環(huán)境部署解決方案詳解

    uni-app多環(huán)境部署解決方案詳解

    uni-app可通過(guò)process.env.NODE_ENV判斷當(dāng)前環(huán)境是開發(fā)環(huán)境還是生產(chǎn)環(huán)境,下面這篇文章主要給大家介紹了關(guān)于uni-app多環(huán)境部署的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • IE8 兼容性問(wèn)題(屬性名區(qū)分大小寫)

    IE8 兼容性問(wèn)題(屬性名區(qū)分大小寫)

    屬性名大小寫問(wèn)題,如屬性window.screen.height
    2009-06-06
  • javascript中l(wèi)ength屬性的探索

    javascript中l(wèi)ength屬性的探索

    本文中,我將會(huì)通過(guò)類數(shù)組對(duì)象(array like object),探索javascript中的length屬性的一些秘密。
    2011-07-07
  • JavaScript隊(duì)列數(shù)據(jù)結(jié)構(gòu)詳解

    JavaScript隊(duì)列數(shù)據(jù)結(jié)構(gòu)詳解

    這篇文章主要介紹了JavaScript隊(duì)列數(shù)據(jù)結(jié)構(gòu)詳解,隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),隊(duì)列中允許兩種基礎(chǔ)操作,也就是插入和刪除,也就是入隊(duì)和出隊(duì)
    2022-07-07
  • 原生js實(shí)現(xiàn)仿window10系統(tǒng)日歷效果的實(shí)例

    原生js實(shí)現(xiàn)仿window10系統(tǒng)日歷效果的實(shí)例

    下面小編就為大家?guī)?lái)一篇原生js實(shí)現(xiàn)仿window10系統(tǒng)日歷效果的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • ES6中解構(gòu)賦值的語(yǔ)法及用法實(shí)例

    ES6中解構(gòu)賦值的語(yǔ)法及用法實(shí)例

    ES6的解構(gòu)賦值是一種快速方便的方法,可以從數(shù)組或?qū)ο笾刑崛≈挡⑵滟x值給變量,下面這篇文章主要給大家介紹了關(guān)于ES6中解構(gòu)賦值的語(yǔ)法及用法的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • JavaScript中removeChild 方法開發(fā)示例代碼

    JavaScript中removeChild 方法開發(fā)示例代碼

    這篇文章主要介紹了JavaScript中removeChild 方法開發(fā)示例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • 用js實(shí)現(xiàn)猜數(shù)字小游戲

    用js實(shí)現(xiàn)猜數(shù)字小游戲

    這篇文章主要為大家詳細(xì)介紹了用js實(shí)現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評(píng)論