新聞中心
本文轉(zhuǎn)載自微信公眾號「神光的編程秘籍」,作者神說要有光。轉(zhuǎn)載本文請聯(lián)系神光的編程秘籍公眾號。

網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、小程序定制開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了蓮池免費建站歡迎大家使用!
魔術(shù)演出
我們準備一個 Node.js 的模塊 input.js:
- // input.js
- function func() {
- return '卡頌'
- }
- module.exports = func();
這個模塊返回的值是啥?
東東:是“卡頌”。
那我在另一個模塊 test.js 中引入這個 input.js,然后打印一下:
- // test.js
- const data = require('./input.js');
- console.log(data);
之后我在 entry.js 里面引入 test.js:
- require('./test.js');
執(zhí)行之后打印的是啥?
東東:是“卡頌”。
真的么?那我們跑一下:
打印的是啥:
東東:是 “卡帥”,哇,好神奇,怎么做到的。
我:想不想學(xué)?
東東:想。
我:那接下來就進入魔術(shù)揭秘時間。
魔術(shù)揭秘
Node.js 加載模塊的流程是這樣的:
模塊加載會調(diào)用 load 方法, load 會調(diào)用對應(yīng)后綴名的 _extensions 的方法來處理,其中會調(diào)用 _compile 來編譯并把結(jié)果放入 cache,之后返回。
所以呢?我們想改變 js 模塊的返回值,只需要改造下 Module._extensions['.js'] 就可以了。
- const Module = require('module');
- const fs = require('fs');
- Module._extensions['.js'] = function (module, filename) {
- let content = fs.readFileSync(filename, 'utf8');
- if (filename.includes('input')) {
- content = content.replace('卡頌', '卡帥');
- }
- module._compile(content, filename);
- };
我們對 filename 為 input 的文件,讀取內(nèi)容之后進行了替換,之后再調(diào)用 module._compile 來編譯,后續(xù)流程不變。
模塊引入方式不變,但是模塊內(nèi)容已經(jīng)悄悄的被修改了,這個魔術(shù)的名字叫做 require hook。
東東:原來是你藏了一段代碼沒展示。
我:魔術(shù)都是這樣的啊。而且你別小看了這個 require hook,它能做到很多強大的功能呢。
東東:哦?比如說
我:比如說 ts-node,它是怎么做到直接 require ts 模塊的?就是通過 require hook 偷偷做了編譯,其實你執(zhí)行的是編譯后的 js。
比如說 babel-register 它是怎么做到直接執(zhí)行帶有 esnext 新特性的代碼的?也是通過 require hook 偷偷做了編譯。
還有覆蓋率測試,其實是通過函數(shù)插樁做到的,也就是你每執(zhí)行一條語句都會計數(shù)。怎么插樁呢?跑單測的時候也沒手動插樁啊,就是因為工具內(nèi)部偷偷通過 require hook 做了插樁,才能得到覆蓋率數(shù)據(jù)。
東東:這個魔術(shù)還挺有用的嘛。學(xué)會了~
總結(jié)
Node.js 的 js 模塊加載的流程是 load -> _extensions['.js'] -> _compile,可以通過修改 _extensions['.js'] 來達到 hook 的目的,比如在 _compile 之前做一些代碼轉(zhuǎn)換。
這種 hook 在 babel-register、ts-node 還有單測的覆蓋率測試中都有應(yīng)用,能夠達到透明的修改代碼的目的。
因為開發(fā)者不知道代碼什么時候被修改的,所以看起來比較神奇。
當(dāng)前文章:給大家變個Node.js的小魔術(shù)
本文網(wǎng)址:http://m.fisionsoft.com.cn/article/cdigdei.html


咨詢
建站咨詢
