当前位置: 首页 > 后端技术 > Node.js

babel原理解析-babel-registeraddHook

时间:2023-04-03 20:52:36 Node.js

babel原理解析-babel-registeraddHook前言希望您在阅读本文时对babel-register有一定的了解。如果还有不明白的可以看下一篇传送门在上一篇文章中已经简单介绍了babel-register的作用,那么babel是如何给require添加一个hook的,这样就可以在require中实现动态编译了node环境(静态编译:unifybabel。动态编译:js编译到这一行时编译)原理分析说明:本文参考代码为babel-0.7.0-beta版本代码。其实在上面的babel-register中可以看到,node环境下babel的编译是通过addHookonrequire的一个解决方案,那么这个hook是如何挂载在require上的呢?首先想到的是node正式版有没有提供native方法处理,官方确实提供了require.extensions方法,可惜已经废弃了,moudle模块没有所谓的添加钩子方法。那我们只能静静的看海盗的实现了。当我们深入pirate的源码时,发现实际的piratenpm包并没有做任何功能。核心代码不超过100行,如下:constModule=module.constructor.length>1?module.constructor:BuiltinModule;exportfunctionaddHook(hook,opts={}){//eslint-disable-lineimport/prefer-default-exportletreversed=false;常量装载机=[];constoldLoaders=[];让分机;constoriginalJSLoader=Module._extensions['.js'];常量匹配器=opts.matcher||无效的;constignoreNodeModules=opts.ignoreNodeModules!==false;exts=opts.extensions||选择.exts||opts.扩展||选择.ext||['.js'];如果(!Array.isArray(exts))exts=[exts];exts.forEach((ext)=>{if(typeofext!=='string')thrownewTypeError(`InvalidExtension:${ext}`);constoldLoader=Module._extensions[ext]||originalJSLoader;oldLoaders[ext]=oldLoader;loaders[ext]=Module._extensions[ext]=functionnewLoader(mod,filename){letcompile;if(!reverted){if(shouldCompile(文件名,exts,匹配器,ignoreNodeModules)){compile=mod._compile;mod._compile=function_compile(code){mod._compile=compile;constnewCode=hook(代码,文件名);if(typeofnewCode!=='string'){thrownewError(HOOK_RETURNED_NOTHING_ERROR_MESSAGE);}返回mod._compile(newCode,文件名);};}}oldLoader(mod,文件名);};});返回函数恢复(){如果(恢复)返回;恢复=真;exts.forEach((ext)=>{if(Module._extensions[ext]===loaders[ext]){Module._extensions[ext]=oldLoaders[ext];}});};}看来这段代码做的事情很简单,就是在原生的moudle方法上不断挂载moudle._extension['.js/.es6/.jsx']等处理函数,没见过执行时间,所以简单写一个democonsole.log('naturelessTT')debugger;require('require.js')babel-nodeindex.js--inspect-brkrun看这个hook的执行时机和调用栈.当实际是require文件时,io读取文件后,会通过moudle.load的方法加载文件,然后依次执行挂载在_extension中的方法。真相大白,但令人意外的是0.7之前的版本竟然没有引入盗版包,看了0.6.26版本,emmmmm,babel老大用了正式版已经标记为过时的require.extensions。当然,虽然废弃了,但是node模块已经被锁定,所以babel老大还在肆无忌惮的使用。当然,0.7已经修改了。已弃用过去,此列表已用于通过按需编译将非JavaScript模块加载到Node.js中。然而,在实践中,有更好的方法可以做到这一点,例如通过其他一些Node.js程序加载模块,或者提前将它们编译成JavaScript。由于模块系统已锁定,此功能可能永远不会消失。但是,它可能有细微的错误和复杂性,最好不要触及。请注意,为了将require(...)语句解析为文件名,模块系统必须执行的文件系统操作的数量与注册扩展的数量成线性比例关系。换句话说,添加扩展会减慢模块加载器的速度,应该不鼓励。