成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

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

一文了解Node中的文件模塊和核心模塊

本篇文章帶大家了解一下Node中的文件模塊和核心模塊,聊聊文件模塊的查找和文件模塊的編譯執行、JavaScript與C/C++ 核心模塊的編譯執行,希望對大家有所幫助!

一文了解Node中的文件模塊和核心模塊

在我們使用 Nodejs 進行日常開發時,經常會使用 require 導入兩類模塊,一類是我們自己編寫的模塊或使用 npm 安裝的第三方模塊,這類模塊在 Node 中稱為 文件模塊;另一類則是 Node 內置的提供給我們使用的模塊,如 osfs 等模塊,這些模塊被稱為 核心模塊。

需要注意的是,文件模塊與核心模塊的差異不僅僅在于是否被 Node 內置,具體到模塊的文件定位、編譯和執行過程,兩者之間都存在明顯的差別。不僅如此,文件模塊還可以被細分為普通文件模塊、自定義模塊或 C/C++ 擴展模塊等等,不同的模塊在文件定位、編譯等流程也存在諸多細節上的不同。

本文會就這些問題,理清文件模塊與核心模塊的概念以及它們在文件定位、編譯或執行等流程的具體過程和需要注意的細節,希望對你有所幫助。

我們先從文件模塊講起。

文件模塊

什么是文件模塊呢?

在 Node 中,使用 .、.. 或 / 開頭的模塊標識符(也就是使用相對路徑或絕對路徑)來 require 的模塊,都會被當作文件模塊。另外,還有一類特殊的模塊,雖然不含有相對路徑或絕對路徑,也不是核心模塊,但是會指向一個包,Node 在定位這類模塊時,會用 模塊路徑 逐個查找該模塊,這類模塊被稱為自定義模塊。

因此,文件模塊包含兩類,一類是帶路徑的普通文件模塊,一類是不帶路徑的自定義模塊。

文件模塊在運行時動態加載,需要完整的文件定位、編譯執行過程,速度比核心模塊慢。

對于文件定位而言,Node 對這兩類文件模塊的處理有所不同。我們來具體看看這兩類文件模塊的查找流程。

普通文件模塊的查找

對于普通的文件模塊,由于攜帶路徑,指向非常明確,查找耗時不會很久,因此查找效率比下文要介紹的自定義模塊要高一些。不過還是有兩點需要注意。

一是通常情況下,使用 require 引入文件模塊時一般都不會指定文件擴展名,比如:

const math = require("math");

由于沒有指定擴展名,Node 還不能確定最終的文件。在這種情況下,Node 會按 .js、.json、.node 的順序補足擴展名,依次嘗試,這個過程被稱為 文件擴展名分析。

另外需要注意的是,在實際開發中,除了 require 一個具體的文件外,我們通常還會指定一個目錄,比如:

const axios = require("../network");

在這種情況下,Node 會先進行文件擴展名分析,如果沒有查找到對應文件,但是得到了一個目錄,此時 Node 會將該目錄當作一個包來處理。

具體而言,Node 會將目錄中的 package.jsonmain 字段所指向的文件作為查找結果返回。如果 main 所指向的文件錯誤,或者壓根不存在 package.json 文件,Node 會使用 index 作為默認文件名,然后依次使用 .js、.node 進行擴展名分析,逐個查找目標文件,如果沒有找到的話就會拋出錯誤。

(當然,由于 Node 存在兩類模塊系統 CJS 和 ESM,除了查找 main 字段外,Node 還會采用其他方式,由于不在本文討論范圍內,就不再贅述了。)

自定義模塊的查找

剛才提到,Node 在查找自定義模塊的過程中,會使用到模塊路徑,那什么是模塊路徑呢?

熟悉模塊解析的朋友應該都知道,模塊路徑是一個由路徑組成的數組,具體的值可以看以下這個示例:

// example.js console.log(module.paths);

打印結果:

一文了解Node中的文件模塊和核心模塊

可以看到,Node 中的模塊存在一個模塊路徑數組,存放在 module.paths 中,用于規定 Node 如何查找當前模塊引用的自定義模塊。

具體來講,Node 會遍歷模塊路徑數組,逐個嘗試其中的路徑,查找該路徑對應的 node_modules 目錄中是否有指定的自定義模塊,如果沒有就向上逐級遞歸,一直到根目錄下的 node_modules 目錄,直到找到目標模塊為止,如果找不到的話就會拋出錯誤。

可以看出,逐級向上遞歸查找 node_modules 目錄是 Node 查找自定義模塊的策略,而模塊路徑便是這個策略的具體實現。

同時我們也得出一個結論,在查找自定義模塊時,層級越深,相應的查找耗時就會越多。因此相比于核心模塊和普通的文件模塊,自定義模塊的加載速度是最慢的。

當然,根據模塊路徑查找到的僅僅是一個目錄,并不是一個具體的文件,在查找到目錄后,同樣地,Node 會根據上文所描述的包處理流程進行查找,具體過程不再贅述了。

以上是普通文件模塊和自定義模塊的文件定位的流程和需要注意的細節,接下來我們來看者兩類模塊是如何編譯執行的。

文件模塊的編譯執行

當定位到 require 所指向的文件后,通常模塊標識符都不帶有擴展名,根據上文提到的文件擴展名分析我們可以知道,Node 支持三種擴展名文件的編譯執行:

  • JavaScript 文件。通過 fs 模塊同步讀取文件后編譯執行。除了 .node.json 文件,其他文件都會被當作 .js 文件載入。

  • .node 文件,這是用 C/C++ 編寫后編譯生成的擴展文件,Node 通過 process.dlopen() 方法加載該文件。

  • json 文件,通過 fs 模塊同步讀取文件后,使用 JSON.parse() 解析并返回結果。

在對文件模塊進行編譯執行之前,Node 會使用如下所示的模塊封裝器對其進行包裝:

(function(exports, require, module, __filename, __dirname) {     // 模塊代碼 });

可以看到,通過模塊封裝器,Node 將模塊包裝進函數作用域中,與其他作用域隔離,避免變量的命名沖突、污染全局作用域等問題,同時,通過傳入 exports、require 參數,使該模塊具備應有的導入與導出能力。這便是 Node 對模塊的實現。

了解了模塊封裝器后,我們先來看 json 文件的編譯執行流程。

json 文件的編譯執行

json 文件的編譯執行是最簡單的。在通過 fs 模塊同步讀取 JSON 文件的內容后,Node 會使用 JSON.parse() 解析出 JavaScript 對象,然后將它賦給該模塊的 exports 對象,最后再返回給引用它的模塊,過程十分簡單粗暴。

JavaScript 文件的編譯執行

在使用模塊包裝器對 JavaScript 文件進行包裝后,包裝之后的代碼會通過 vm 模塊的 runInThisContext()(類似 eval) 方法執行,返回一個 function 對象。

然后,將該 JavaScript 模塊的 exports、require、module 等參數傳遞給這個 function 執行,執行之后,模塊的 exports 屬性被返回給調用方,這就是 JavaScript 文件的編譯執行過程。

C/C++ 擴展模塊的編譯執行

在講解 C/C++ 擴展模塊的編譯執行之前,先介紹一下什么是 C/C++ 擴展模塊。

C/C++ 擴展模塊屬于文件模塊中的一類,顧名思義,這類模塊由 C/C++ 編寫,與 JavaScript 模塊的區別在于其加載之后不需要編譯,直接執行之后就可以被外部調用了,因此其加載速度比 JavaScript 模塊略快。相比于用 JS 編寫的文件模塊,C/C++ 擴展模塊明顯更具有性能上的優勢。對于 Node 核心模塊中無法覆蓋的功能或者有特定的性能需求,用戶可以編寫 C/C++ 擴展模塊來達到目的。

.node 文件又是什么呢,它跟 C/C++ 擴展模塊有什么關系?

事實上,編寫好之后的 C/C++ 擴展模塊經過編譯之后就生成了 .node 文件。也就是說,作為模塊的使用者,我們并不直接引入 C/C++ 擴展模塊的源代碼,而是引入 C/C++ 擴展模塊經過編譯之后的二進制文件。因此,.node 文件并不需要編譯,Node 在查找到 .node 文件后,只需加載和執行該文件即可。在執行的過程中,模塊的 exports 對象被填充,然后返回給調用者。

值得注意的是,C/C++ 擴展模塊編譯生成的 .node 文件在不同平臺下有不同的形式:在 *nix 系統下C/C++ 擴展模塊被 g++/gcc 等編譯器編譯為動態鏈接共享對象文件,擴展名為 .so;在 Windows 下則被 Visual C++ 編譯器編譯為動態鏈接庫文件,擴展名為 .dll。但是在我們實際使用時使用的擴展名卻是 .node,事實上 .node 的擴展名只是為了看起來更自然一點,實際上,在 Windows 下它是一個 .dll 文件,在 *nix 下則是一個 .so 文件。

Node 在查找到要 require 的 .node 文件之后,會調用 process.dlopen() 方法對該文件進行加載和執行。由于 .node 文件在不同平臺下是不同的文件形式,為了實現跨平臺,dlopen() 方法在 Windows*nix 平臺下分別有不同的實現,然后通過 libuv 兼容層進行封裝。下圖是 C/C++ 擴展模塊在不同平臺下編譯和加載的過程:

一文了解Node中的文件模塊和核心模塊

核心模塊

核心模塊在 Node 源代碼的編譯過程中,就編譯進了二進制執行文件。在 Node 進程啟動時,部分核心模塊就被直接加載進內存中,所以這部分核心模塊引入時,文件定位和編譯執行這兩個步驟可以省略掉,并且在路徑分析中會比文件模塊優先判斷,所以它的加載速度是最快的。

核心模塊其實分為 C/C++ 編寫的和 JavaScript 編寫的兩部分,其中 C/C++ 文件存放在 Node 項目的 src 目錄下,JavaScript 文件存放在 lib 目錄下。顯然,這兩部分模塊的編譯執行流程都有所不同。

JavaScript 核心模塊的編譯執行

對于 JavaScript 核心模塊的編譯,在 Node 源代碼的編譯過程中,Node 會采用 V8 附帶的 js2c.py 工具,將所有內置的 JavaScript 代碼,包括 JavaScript 核心模塊,轉換為 C++ 里的數組,JavaScript 代碼就這樣以字符串的形式存儲在 node 命名空間中。在啟動 Node 進程時,JavaScript 代碼就會直接加載進內存。

當引入 JavaScript 核心模塊時,Node 會調用 process.binding() 通過模塊標識符分析定位到其在內存中的位置,將其取出。在取出后,JavaScript 核心模塊同樣會經歷模塊包裝器的包裝,然后被執行,導出 exports 對象,返回給調用者。

C/C++ 核心模塊的編譯執行

在核心模塊中,有些模塊全部由 C/C++ 編寫,有些模塊則由 C/C++ 完成核心部分,其他部分則由 JavaScript 實現包裝或向外導出,以滿足性能需求,像 buffer、fsos 等模塊都是部分通過 C/C++ 編寫的。這種 C++ 模塊主內完成核心,JavaScript 模塊主外實現封裝的模式是 Node 提高性能的常見方式。

核心模塊中由純 C/C++ 編寫的部分稱為內建模塊,如 node_fsnode_os 等,它們通常不被用戶直接調用,而是被 JavaScript 核心模塊直接依賴。因此,在 Node 的核心模塊的引入過程中,存在這樣一條引用鏈:

一文了解Node中的文件模塊和核心模塊

那 JavaScript 核心模塊是如何加載內建模塊的呢?

還記得 process.binding() 方法嗎,Node 通過調用該方法實現將 JavaScript 核心模塊從內存中取出。該方法同樣適用于 JavaScript 核心模塊,來協助加載內建模塊。

具體到該方法的實現,加載內建模塊時,首先創建一個 exports 空對象,然后調用 get_builtin_module() 方法取出內建模塊對象,通過執行 register_func() 填充 exports 對象,最后返回給調用方完成導出。這就是內建模塊的加載和執行過程。

通過以上分析,對于引入核心模塊這樣一條引用鏈,以 os 模塊為例,大致的流程如下:

一文了解Node中的文件模塊和核心模塊

總結來說,引入 os 模塊的過程經歷 JavaScript 文件模塊的引入、JavaScript 核心模塊的加載和執行和內建模塊的加載執行,過程十分繁瑣復雜,但是對于模塊的調用者來說,由于屏蔽了底層的復雜實現和細節,僅僅通過 require() 就可完成整個模塊的導入,十分簡潔。友好。

總結

本文介紹了文件模塊與核心模塊的基本概念以及它們在文件定位、編譯或執行等流程的具體過程和需要注意的細節。具體而言:

  • 文件模塊根據文件定位過程的不同可以分為普通文件模塊和自定義模塊。普通文件模塊由于路徑明確,可以直接定位,有時會涉及到文件擴展名分析、目錄分析的過程;自定義模塊會根據模塊路徑進行查找,查找成功之后也會通過目錄分析進行最終的文件定位。

  • 文件模塊根據編譯執行流程的不同可以分為 JavaScript 模塊和 C/C++ 擴展模塊。JavaScript 模塊被模塊封裝器包裝之后通過 vm 模塊的 runInThisContext 方法進行執行;C/C++ 擴展模塊由于已經是經過編譯之后生成的可執行文件,因此可直接執行,返回導出對象給調用方。

  • 核心模塊分為 JavaScript 核心模塊和內建模塊。JavaScript 核心模塊在 Node 進程啟動時便被加載進內存中,通過 process.binding() 方法可將其取出,然后執行;內建模塊的編譯執行會經歷 process.binding()、get_builtin_module()register_func() 函數的處理。

除此之外,我們還得出了 Node 引入核心模塊的引用鏈,即文件模塊–>JavaScript 核心模塊–>內建模塊,也學習了 C++ 模塊主內完成核心,JavaScript 模塊主外實現封裝的模塊編寫方式。

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
精品无码人妻一区二区三区四| 精品无码成人片一区二区| 国产性夜夜春夜夜爽| 狠狠色丁香久久婷婷综| 久久精品亚洲精品无码白云TV| 久久老司机精品网站福利| 蜜桃精品欧美一区二区三区| 欧美XXXXX牲另类人与| 人人妻人人妻人人人人妻妻人人人人| 肉大捧一进一出免费视频| 无码精品毛片波多野结衣| 亚洲AV永久无码精品九之| 亚洲综合色婷婷七月丁香| 91久久精品www人人做人人爽| 八戒八戒神马手机在线高清观看W| 风流老熟女一区二区三区| 国产精品青青青高清在线| 精品国产三级A在线观看| 久久久久久精品天堂无码中文字幕| 欧产日产国产精品| 牲交A欧美牲交AⅤ免费一| 亚洲 日韩 另类 制服 无码| 亚洲在AV人极品无码网站| YY6090新视觉影院| 国产伦精品一区二区三区免费| 久久久久久精品成人鲁丝电影 | 各种女BBWBBWBBW么| 黑人大荫道BBWBBB高潮潮喷| 蜜芽久久人人超碰爱香蕉| 日欧 片内射AV在线影院| 亚洲丰满少妇XXXXⅩ高潮| 2823理论片在线播放| 国产69囗曝吞精在线视频| 久久AV高潮AV无码AV| 人妻妺妺窝人体色777777| 亚洲AV人无码激艳猛片| 42岁女子20天断崖式衰老| 国产成人无码精品XXXX| 巨RU麻麻奶水雪白肥美喷| 色天使色偷偷色噜噜| 亚洲日本高清成人AⅤ片| 啊别插了视频高清在线观看| 国语自产偷拍精品视频偷| 女教师の爆乳BD在线观看| 偷窥妇科TUBESEX妇| 在线观看4480私人影视| 高清不卡亚洲日韩AV在线| 久久久久久久精品成人热色戒| 日韩无码视频专区| 亚洲综合AV一区二区三区| 东北少妇大叫高潮XXXⅩ| 久久精品国产亚洲AV无码偷窥 | 国产精品99久久精品| 久久综合色天天久久综合图片| 少妇饥渴偷公乱第一章全文| 一边摸一边做爽的视频17国产| 公交车舒婷1一20全文| 乱亲女H秽乱长久久久| 婷婷妺妺窝人体色www久久| 在线观看免费AV网站| 国产精品自在线拍国产手机版| 男朋友把舌头都伸进我的嘴巴里了 | 看着领导挺进娇妻的体内电影| 四虎国产精品永久入口| 中文字幕人妻不在线无码视频| 国产精品亚洲А∨天堂2018| 欧美美女多人群交视频| 亚洲丰满熟妇乱XXXXX网站| 成人H动漫精品一区二区| 久久午夜夜伦鲁鲁片无码免费| 无码人妻出轨与黑人中文字幕| GAYFUCKⅩⅩⅩⅩHD警察| 精品少妇爆乳无码av专用区| 撕掉她的衣服吮的双乳游戏 | 亚洲精品第一国产综合麻豆| 粗大的内捧猛烈进出在线视频 | 国精品产露脸偷拍视频| 日韩精品一区二区三区在线观看L| 一二三四视频中文字幕| 国产免费不卡午夜福利在线| 人人妻人人妻人人片AV| 中国性猛交ⅩXXX免费看| 国内美女推油按摩在线播放| 少妇扒开腿让我爽了一夜| 2020精品国产自在现线看| 狠狠色丁香久久婷婷综| 天天综合网网欲色| 被黑人的大JJ干得很舒服吗| 美女爆乳裸体WWW免费网站| 亚洲成av人无码| 国产精品成人一区无码| 日本大一大二大三在一起读吗| 中文字幕精品亚洲一区| 久久WWW色情成人免费观看| 无码熟熟妇丰满人妻啪啪软件| 成 人 黄 色 网站 S色| 你的棒棒可以桶桶我的下水道| 亚洲色偷偷偷网站色偷一区人人澡| 国产精品免费久久久久影院| 日日日日做夜夜夜夜无码| WWW.一区二区三区在线 || 免费国内接码在线接收| 亚洲一区二区三区小说| 精品国产一区二区三区久久久狼| 无码中文亚洲AV吉吉影音先锋| 顶级RAPPER潮水日本| 强行入侵粗暴完整版| 97久久国产亚洲精品超碰热| 狂猛欧美激情性XXXX大豆行情| 亚洲精品无码寂寞少妇AV| 国精产品一二三四线| 无码少妇一区二区浪潮AV| 高H乱好爽要尿了潮喷了| 日韩精品久久久久久免费| А√天堂BT中文在线| 欧美日韩国产免费一区二区三区| 中文字幕日产无线码一区| 巨人精品福利官方导航| 亚洲最大成人AV在线天堂网 | 国产精华液一线二线三线区别| 色狠狠熟女AV一区二区三区| 成人欧美一区二区三区在线观看| 热99RE久久精品这里都是精品| 98在线视频噜噜噜国产| 男人J桶进女人P无遮挡全过程 | 妺妺窝人体色WWW在线韩国| 中国WINDOWS野外| 快拨出天我是你母亲| 呦交小U女国产精品视频| 久久婷婷五月综合色99啪| 亚洲综合无码AV一区二区| 久久久久人妻一区精品果冻| 野花高清在线观看免费官网中文版| 久久国产乱子伦免费精品无码| 亚洲欧美日本中文字不卡| 精品国产乱码久久久久久人妻| 亚洲日韩AV无码中文| 久久久久久精品免费不卡| 夜夜澡人摸人人添人人看| 久章草在线毛片视频播放| 18禁勿入免费网站入口不卡| 欧美18ⅩXOO极品| 啊灬啊灬啊灬快灬高潮了女| 人妻少妇一区二区| 夫妇联欢会回不去的夜晚| 无码A级毛片免费视频内谢| 国产又大又硬又粗| 亚洲人交乣女BBW| 麻豆亚洲AV成人无码久久精品| 27报女上男下动态图GIF图| 人妻少妇乱孑伦无码专区蜜柚 | 午夜福利麻豆国产精品| 幻女FREE性俄罗斯毛片福| 阳台顶着岳刘晓莉的肥臀| 免费观看高清日本AⅤ| YSL千人千色T9T9T9| 色综合色狠狠天天综合色| 国产精品自在在线午夜| 亚洲欧洲无卡二区视頻| 免费A级毛片无码免费视频1| 啊轻点灬大JI巴太粗太长了在线| 色天天躁夜夜躁天干天干| 国产成人一区二区三区影院| 亚洲AV五十路在线观看| 浪荡女天天不停挨CAO日常视频| 99精品国产成人一区二区| 日日狠狠久久8888偷偷色| 国产肉体XXXX裸体137大胆| 亚洲人成国产精品无码果冻| 蜜臀久久久久精品久久久| 槽溜2021入口一二三四| 小浪货腿张开水好多呀H| 久久国产加勒比精品无码| 99亚洲乱人伦AⅤ精品| 少妇人妻大乳在线视频不卡| 韩日午夜在线资源一区二区| 中国农村真卖BBWBBW| 日日摸夜夜添夜夜添毛片性色AV| 国产未成女一区二区三区| 一边做饭一边躁狂我会怎么样呢 | 爱情岛论坛自拍亚洲品质极速福利| 婷婷五月六月激情综合色中文字幕| 妓女院18禁止观看| AV无码动漫一区二区三区精品| 天天爽狠狠噜天天噜日日噜| 精品日韩欧美一区二区在线播放| 99无人区码一码二码三| 无码成人亚洲AV污污污在线看| 久久精品人人槡人妻人人玩AV| А天堂中文地址在线| 亚洲AⅤ无码牛牛影视| 免费A级毛片无码免费视频1| 国产超薄肉色丝袜视频| 亚洲中文字幕无码中文字| 日本又黄又爽GIF动态图| 精品 亚洲 无码 自拍 另类| XXXXBBBB欧美残疾人| 亚洲成AV人在线观看网站| 青草伊人久久综在合线亚洲| 好紧真爽喷水高潮视频办公室|