gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

一文聊聊Node.js中的模塊路徑解析

本篇文章帶大家了解一下Node.js中的模塊路徑解析,介紹一下Node模塊路徑解析方法,希望對大家有所幫助!

一文聊聊Node.js中的模塊路徑解析

require案例

  • 當前有一個項目
  • 當前項目路徑/Users/rainbow/Documents/前端/腳手架開發/rainbow-test
  • 項目bin目錄下有一堆文件

一文聊聊Node.js中的模塊路徑解析

  • /bin/index.js
console.log(require.resolve(".")); // /Users/rainbow/Documents/前端/腳手架開發/rainbow-test/bin/index.js  輸出bin/index.js的絕對路徑 console.log(require.resolve.paths(".")); // [ '/Users/rainbow/Documents/前端/腳手架開發/rainbow-test/bin' ] 輸出的文件可能在的路徑的數組
console.log(require.resolve("yargs")); // /Users/rainbow/Documents/前端/腳手架開發/rainbow-test/node_modules/yargs/index.cjs console.log(require.resolve.paths("yargs")); /* [   '/Users/rainbow/Documents/前端/腳手架開發/rainbow-test/bin/node_modules',   '/Users/rainbow/Documents/前端/腳手架開發/rainbow-test/node_modules',   '/Users/rainbow/Documents/前端/腳手架開發/node_modules',   '/Users/rainbow/Documents/前端/node_modules',   '/Users/rainbow/Documents/node_modules',   '/Users/rainbow/node_modules',   '/Users/node_modules',   '/node_modules',   '/Users/rainbow/.node_modules',   '/Users/rainbow/.node_libraries',   '/usr/local/Cellar/node/14.3.0_1/lib/node' ] */

require解析并找到模塊執行文件的流程

1、Nodejs項目模塊路徑解析是通過require.resolve方式實現的。

  • require.resolve就是通過Module._resolveFileName方法實現的
  • Module._resolveFileName核心流程是:
    • 判斷該路徑是否是內置模塊
    • 不是,則通過Module._resolveLookupPahts方法,生成node_modules可能存在的路徑,如果傳入的路徑是’/test/lerna/cli.js’,在每一級路徑下加上node_moduels的路徑數組
    • 通過Module._findPath查詢模塊的真實路徑,

2、Module._findPath核心流程是:

  • 查詢緩存(將request和paths通過x00合并生成cacheKey)
  • 遍歷 Module._resolveLookupPahts方法生成的paths數組,將pathrequest組成文件路徑basePath
  • 如果basePath存在則調用fs.realPahtSync獲取文件的真實路徑
  • 將文件真實路徑緩存到Module._pathCache(key為cacheKey)(Module._pathCache就是一個map)

3、fs.realPahtSync核心流程:

  • 查詢緩存(緩存的key為p。即Module._findPath中生成的路徑)
  • 從左往右遍歷路徑字符串,查詢到/時,拆分路徑,判斷該路徑是否為軟鏈接,如果是軟鏈接則查詢真實鏈接,并生成新路徑p,然后繼續讓后遍歷,這里有一個細節:
  • 遍歷過程中生成的子路徑base會緩存在knownHard和cache中,避免重復查詢
  • 遍歷完成得到模塊對應的真實路徑,此時會將原始路徑original作為key,真實路徑作為value,保存到緩存中

4、require.resolve.paths等價于Module._resolveLookupPaths,該方法獲取所有node_modules可能存在的路徑組成一個數組。

5、require.resolve.paths實現原理是:

  • 如果是/(根路徑)直接返回['/node_modules']
  • 否則,將路徑字符串從后往前遍歷,查詢到/時,拆分路徑,在后面加上node_modules,并傳入一個paths數組,直到查詢不到/后返回paths數組

require使用到內置模塊的方法

當我們使用require('yargs')

require方法

  • 實際使用的是Module._load方法
Module.prototype.require = function(id) { //id = 'yargs'   validateString(id, 'id');   if (id === '') {     throw new ERR_INVALID_ARG_VALUE('id', id, 'must be a non-empty string');   }   requireDepth++;   try {     return Module._load(id, this, /* isMain */ false);   } finally {     requireDepth--;   } };
// 參數 id = 'yargs' this={  paths: Module._nodeModulePaths(process.cwd()) }

Module._nodeModulePaths方法

一文聊聊Node.js中的模塊路徑解析

// 進入mac電腦所在的邏輯: // from => /Users/rainbow/Documents/前端/腳手架開發/lerna源碼/lernas  //'from' is the __dirname of the module.   Module._nodeModulePaths = function(from) {     from = path.resolve(from);     // Return early not only to avoid unnecessary work, but to *avoid* returning     // an array of two items for a root: [ '//node_modules', '/node_modules' ]     if (from === '/')       return ['/node_modules'];      const paths = [];         // 關鍵算法代碼     for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {       const code = from.charCodeAt(i);       if (code === CHAR_FORWARD_SLASH) {         if (p !== nmLen)           paths.push(from.slice(0, last) + '/node_modules');         last = i;         p = 0;       } else if (p !== -1) {         if (nmChars[p] === code) {           ++p;         } else {           p = -1;         }       }     }      // Append /node_modules to handle root paths.     paths.push('/node_modules');      return paths;   };

for循環的核心算法解析:

一文聊聊Node.js中的模塊路徑解析

Module._load方法

Module._load(id, this, /* isMain */ false)

核心實現代碼是:const filename = Module._resolveFilename(request, parent, isMain);

require.resolve

Node.js項目模塊路徑解析是通過require.resolve方式實現的。

  • require.resolve就是通過Module._resolveFileName方法實現的,
// node.js內置模塊require的源代碼 function resolve(request, options) {   validateString(request, 'request');   return Module._resolveFilename(request, mod, false, options); //核心實現 }  require.resolve = resolve;  function paths(request) {   validateString(request, 'request');   return Module._resolveLookupPaths(request, mod); //核心代碼 }  resolve.paths = paths;

Module._resolveFileName核心流程

  • 判斷該路徑是否是內置模塊
  • 不是,則通過Module._resolveLookupPahts方法,將paths和環境中的路徑結合起來
  • 通過Module._findPath查詢模塊的真實路徑

return Module._resolveFilename(request, parent, isMain);

一文聊聊Node.js中的模塊路徑解析

Module._resolveFilename = function(request, parent, isMain, options) {   if (NativeModule.canBeRequiredByUsers(request)) { //是否為內置模塊     return request;   }    let paths;   // 讓paths和環境變量中的paths結合   paths = Module._resolveLookupPaths(request, parent); //核心代碼      if (parent && parent.filename) {     // 讀取filename對應的package.json文件,看是否有exports字段,當前filename = false     const filename = trySelf(parent.filename, request);     if (filename) { //false       const cacheKey = request + 'x00' +           (paths.length === 1 ? paths[0] : paths.join('x00'));       Module._pathCache[cacheKey] = filename;       return filename;     }   }   //關鍵代碼,找到本地執行文件 // Look up the filename first, since that's the cache key.    const filename = Module._findPath(request, paths, isMain, false);   if (filename) return filename;   // ... };

Module._resolveLookupPahts方法

  • 生成要查找模塊的所有路徑上可能存在node_modules的路徑數組
  • require.resolve.paths("yargs")核心實現方法

生成

[   '/Users/rainbow/Documents/前端/腳手架開發/rainbow-test/bin/node_modules',   '/Users/rainbow/Documents/前端/腳手架開發/rainbow-test/node_modules',   '/Users/rainbow/Documents/前端/腳手架開發/node_modules',   '/Users/rainbow/Documents/前端/node_modules',   '/Users/rainbow/Documents/node_modules',   '/Users/rainbow/node_modules',   '/Users/node_modules',   '/node_modules',   '/Users/rainbow/.node_modules',   '/Users/rainbow/.node_libraries',   '/usr/local/Cellar/node/14.3.0_1/lib/node' ]

一文聊聊Node.js中的模塊路徑解析

Module._resolveLookupPaths = function(request, parent) {   if (NativeModule.canBeRequiredByUsers(request)) {     debug('looking for %j in []', request);     return null;   }    // Check for node modules paths.   if (request.charAt(0) !== '.' ||       (request.length > 1 &&       request.charAt(1) !== '.' &&       request.charAt(1) !== '/' &&       (!isWindows || request.charAt(1) !== ''))){      let paths = modulePaths;      if (parent != null && parent.paths && parent.paths.length) {       paths = parent.paths.concat(paths);     }      debug('looking for %j in %j', request, paths);     return paths.length > 0 ? paths : null;   }      // In REPL, parent.filename is null.   if (!parent || !parent.id || !parent.filename) {     // Make require('./path/to/foo') work - normally the path is taken     // from realpath(__filename) but in REPL there is no filename     const mainPaths = ['.'];      debug('looking for %j in %j', request, mainPaths);     return mainPaths;   }    debug('RELATIVE: requested: %s from parent.id %s', request, parent.id);    const parentDir = [path.dirname(parent.filename)];   debug('looking for %j', parentDir);   return parentDir; };

Module._findPath核心流程

  • 查詢緩存(將request和paths通過x00合并生成cacheKey)(x00是空格的16進制)
  • 遍歷Module._resolveLookupPahts方法生成的paths數組,將pathrequest組成文件路徑basePath
  • 如果basePath存在則調用fs.realPahtSync獲取文件的真實路徑

一文聊聊Node.js中的模塊路徑解析

fs.realPahtSync

一文聊聊Node.js中的模塊路徑解析

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
亚洲另类第一页| 天天干天天色天天爽| 热99这里只有精品| 超碰10000| 欧美亚洲色图视频| 青青草视频在线视频| 黄色网络在线观看| 日韩a级黄色片| 999一区二区三区| 国产女大学生av| 国产91在线视频观看| 波多野结衣50连登视频| 国产日韩成人内射视频| 亚洲娇小娇小娇小| 手机在线视频你懂的| 无码 制服 丝袜 国产 另类| 熟女少妇在线视频播放| 色婷婷综合久久久久中文字幕| 亚洲国产高清av| 污免费在线观看| 精品少妇在线视频| 成人亚洲视频在线观看| 亚洲在线观看网站| 男女猛烈激情xx00免费视频| aaaaaa亚洲| 最新av免费在线观看| 黄色一级片黄色| 久久国产精品国产精品| 嫩草影院中文字幕| 中文字幕视频在线免费观看| 亚洲一级片免费观看| 欧美v在线观看| 欧美h视频在线观看| 337p粉嫩大胆噜噜噜鲁| 亚洲天堂av一区二区| 九一国产精品视频| 爽爽爽在线观看| 欧美日韩激情视频在线观看 | 色中文字幕在线观看| 美女扒开大腿让男人桶| 国产理论在线播放| 高清欧美精品xxxxx| 伊人免费视频二| 欧美一级黄色影院| 欧妇女乱妇女乱视频| 欧美成人乱码一二三四区免费| 久久久久久久久久伊人| 九九热免费在线观看| 国产熟女高潮视频| 91.com在线| 免费观看黄色大片| 日本美女视频一区| 久久人妻精品白浆国产| 国内精品在线观看视频| 精品少妇人妻av一区二区| 欧美第一页浮力影院| 国产真人无码作爱视频免费| 久久久亚洲精品无码| 免费看日b视频| www.亚洲一区二区| 亚洲一区二区三区观看| www.se五月| 国产永久免费网站| 手机版av在线| 一级做a免费视频| 一级黄色在线播放| 色18美女社区| 一区二区三区日韩视频| 欧美爱爱视频网站| 亚洲av首页在线| 国产一区二区三区播放| 精品一区二区三区毛片| 国产精品jizz在线观看老狼| 五月六月丁香婷婷| 欧美做受777cos| www.av91| 日韩少妇内射免费播放18禁裸乳| 欧美一区二区中文字幕| 男女av免费观看| 欧美伦理片在线观看| 中文字幕一区二区在线观看视频| 亚洲精品国产久| 国产一二三区在线播放| 97视频在线免费播放| www欧美激情| 在线观看成人免费| 欧美精品自拍视频| 天天爽天天爽夜夜爽| 黄瓜视频免费观看在线观看www| 99久re热视频精品98| 欧美日韩在线视频一区二区三区| 欧美黄色一级片视频| 国产大片一区二区三区| 男女猛烈激情xx00免费视频| 成人性做爰aaa片免费看不忠| 男女污污的视频| 青春草国产视频| 日本xxxx黄色| 人人妻人人添人人爽欧美一区| 亚洲免费看av| 黄页网站大全在线观看| 亚洲一区二区福利视频| 国产h视频在线播放| 亚洲精品手机在线观看| 国产96在线 | 亚洲| 久久久久xxxx| 国产三区在线视频| 香港三级日本三级a视频| 五月天婷婷激情视频| 国产九九九九九| 国产又大又长又粗又黄| 免费看a级黄色片| 国产美女在线一区| 日本黄网站色大片免费观看| 网站一区二区三区| 成人三级视频在线播放| 日韩一级特黄毛片| 国产福利精品一区二区三区| 久久精品视频91| 日本在线观看a| 韩日视频在线观看| 一二三四中文字幕| 99精品一级欧美片免费播放| 日韩精品一区中文字幕| 内射国产内射夫妻免费频道| 国产成人艳妇aa视频在线| 男女啪啪的视频| 国产成人精品免费看在线播放| 嫩草影院国产精品| 一区二区xxx| 57pao国产成永久免费视频| 超碰网在线观看| av免费网站观看| www.xxx亚洲| 亚洲黄色小视频在线观看| 日本久久久久久久久久久久| 老司机午夜av| 亚洲天堂网2018| 久久av喷吹av高潮av| 亚洲黄色网址在线观看| 强开小嫩苞一区二区三区网站| 国产成人三级视频| www.日本在线视频| 国产亚洲欧美在线视频| 91激情视频在线| 视频免费1区二区三区| 日韩中文在线字幕| 欧美日韩精品在线一区二区 | 黄色av免费在线播放| 视频二区在线播放| 伊人网在线免费| 亚洲乱码中文字幕久久孕妇黑人| 国产免费成人在线| 午夜大片在线观看| 日韩一级特黄毛片| 日韩中文字幕三区| 五月天视频在线观看| 国产天堂视频在线观看| 精品视频无码一区二区三区| 九一精品久久久| 自拍日韩亚洲一区在线| jizz欧美性11| 黄色一级视频在线播放| 日本一二区免费| 日韩欧美不卡在线| 久久精品亚洲天堂| 国产免费黄视频| 无码人妻精品一区二区三区99v| 999一区二区三区| 中文字幕成人免费视频| 精品久久一二三| 三日本三级少妇三级99| 黄色一级片播放| 成年在线观看视频| 成人综合久久网| 激情婷婷综合网| 国产又粗又猛又爽又黄的网站| 国产91色在线观看| 免费观看精品视频| 免费拍拍拍网站| 日本精品免费视频| 99日在线视频| 国产野外作爱视频播放| 激情六月丁香婷婷| 97视频久久久| 欧美乱大交xxxxx潮喷l头像| 蜜臀av.com| 日韩不卡的av| 一级网站在线观看| 亚洲免费av一区| 日韩不卡一二三| 亚洲欧美在线精品| 别急慢慢来1978如如2| 91av资源网| 噜噜噜久久亚洲精品国产品麻豆| 免费成人深夜夜行网站视频| 97人人模人人爽人人澡| 中文字幕第三区| 亚洲天堂第一区| 日韩成人三级视频|