
本文转载自微信公众号「神光的大个编程秘籍」,作者神说要有光。家变转载本文请联系神光的小魔编程秘籍公众号。
我们准备一个 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);执行之后打印的小魔是啥?
东东:是“卡颂”。
真的大个么?那我们跑一下:

打印的是啥:
东东:是 “卡帅”,哇,家变好神奇,小魔怎么做到的大个。
我:想不想学?家变
东东:想。
我:那接下来就进入魔术揭秘时间。小魔
Node.js 加载模块的大个流程是这样的:

模块加载会调用 load 方法, load 会调用对应后缀名的家变 _extensions 的方法来处理,其中会调用 _compile 来编译并把结果放入 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 的文件,读取内容之后进行了替换,之后再调用 module._compile 来编译,后续流程不变。
模块引入方式不变,但是模块内容已经悄悄的被修改了,这个魔术的名字叫做 require hook。
东东:原来是你藏了一段代码没展示。
我:魔术都是这样的啊。而且你别小看了这个 require hook,它能做到很多强大的功能呢。
东东:哦?比如说
我:比如说 ts-node,它是怎么做到直接 require ts 模块的?就是通过 require hook 偷偷做了编译,其实你执行的是编译后的 js。
比如说 babel-register 它是WordPress模板怎么做到直接执行带有 esnext 新特性的代码的?也是通过 require hook 偷偷做了编译。
还有覆盖率测试,其实是通过函数插桩做到的,也就是你每执行一条语句都会计数。怎么插桩呢?跑单测的时候也没手动插桩啊,就是因为工具内部偷偷通过 require hook 做了插桩,才能得到覆盖率数据。
东东:这个魔术还挺有用的嘛。学会了~
Node.js 的 js 模块加载的流程是 load -> _extensions[.js] -> _compile,可以通过修改 _extensions[.js] 来达到 hook 的目的,比如在 _compile 之前做一些代码转换。
这种 hook 在 babel-register、ts-node 还有单测的覆盖率测试中都有应用,能够达到透明的修改代码的目的。
因为开发者不知道代码什么时候被修改的云服务器,所以看起来比较神奇。
相关文章:
源码库服务器租用IT技术网香港云服务器益华科技源码下载IT资讯网亿华云企商汇益强编程堂益强编程舍智能时代益强IT技术网全栈开发益强科技IT资讯网益强智未来益强科技益强前沿资讯亿华智造益华科技亿华云亿华科技极客码头亿华智慧云码上建站码力社亿华互联科技前瞻创站工坊益强资讯优选多维IT资讯技术快报思维库益强数据堂云站无忧亿华灵动益强智囊团益华IT技术论坛运维纵横极客编程亿华云计算云智核
0.1587s , 11667.0546875 kb
Copyright © 2025 Powered by 给大家变个 Node.js 的小魔术,亿华互联 滇ICP备2023000592号-16