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

babel各单元介绍&如何写一个babel插件

时间:2023-04-03 14:17:58 Node.js

Babelbabel是如何工作的?parse->AST->transform->gengerate如何编译js->ASTbabel应用场景语法糖polyfill代码统一hack相关概念介绍babel-polyfill依赖core-js,提供es*->es3方法,只转换语法,不转换convertAPI(likePromise,WeakMap)babel-helperbabel-register(0.7.0-beta)Babel的基础配置init使用pirate劫持require,在hook中执行babel。缓存代码,提高babel下次运行的效率constenv=babel.getEnv(false);如果(env)cacheKey+=`:${env}`;//读取缓存根据mtime判断是否需要重新babelif(cache){constcached=cache[cacheKey];if(cached&&cached.mtime===mtime(filename)){returncached.code;}}constresult=babel.transform(code,{...opts,sourceMaps:opts.sourceMaps===undefined?"both":opts.sourceMaps,ast:false,});如果(缓存){缓存[缓存键]=结果;结果.mtime=mtime(文件名);}if(result.map){if(Object.keys(maps).length===0){installSourceMapSupport();}maps[文件名]=result.map;}returnresult.code;}//hookpassedext配置函数hookExtensions(exts){if(piratesRevert)piratesRevert();piratesRevert=addHook(compile,{exts,ignoreNodeModules:false});}//Entryfunctionexportdefaultfunctionregister(opts?:Object={}){//克隆以避免用下面的“删除”改变参数对象。opts=Object.assign({},opts);如果(opts.extensions)hookExtensions(opts.extensions);如果(opts.cache===false&&缓存){registerCache.clear();缓存=空;}elseif(opts.cache!==false&&!cache){registerCache.load();缓存=registerCache.get();}...}babel-core提供了一个基本的transform方法如何写一个babel插件babel-plugin其实是对从代码中转过来的AST进行操作和准备工具AST转换工具AST转换可视化工具ast的解构可以类比到树或json嵌套结构,其结构的每一层都可以称为一个节点。如下图,babel提供了一个visitor方法,允许我们在里面指定我们想要什么。需要访问的节点,当节点被命中时可以做一个自定义的操作实例分析AST中有什么样的节点结构,比如console.log('a')每个节点实际的AST展示如下。这里就不细说了,可以参考文章末尾的babel手册2这里直接贴代码module.exports=function(babel){const{types:t,template}=babel;constvisitor={//required要访问的节点名称//accessor会默认注入两个参数path(类比dom),stateExpressionStatement(path,state){constnode=path.node;//扩展当前节点内部访问,判断是否符合console解析出的astconstexpressionNode=keyPathVisitor(node,['expression']);constisCallExpression=expressionNode.type==='CallExpression';if(isCallExpression){constobjectName=keyPathVisitor(expressionNode,['callee','object','name']);constprototypeName=keyPathVisitor(expressionNode,['callee','property','name']);if(objectName==='console'&&prototypeName==='log'&&!MAC){//满足以上条件,直接移除节点path.remove();}}}};返回{访客};};3.进阶版:如果我们要在babel-plugin中添加代码,差不多有3种方法A:手动添加节点(很恶心~相信你不会想明白的)B:生成ast先生,直接path.insertBeforeC:Usingbabel-template示例:去除autobind装饰器,在构造函数中自动绑定this注1.因为babel是根据修改时间来判断babel是否是,所以babel插件如果要在当前env中生效需要添加写入BABEL_DISABLE_CACHE后实时//babel-register/cache.jsfunctionload(){if(process.env.BABEL_DISABLE_CACHE)return;process.on("退出",保存);process.nextTick(保存);如果(!_fs2.default.existsSync(FILENAME))返回;尝试{data=JSON.parse(_fs2.default.readFileSync(FILENAME));}catch(err){返回;}}2.记得加babel-plugin-prefix,因为babelrc中配置的插件名在babel加载时会统一以babel-plugin为前缀,然后在模块系统中找找题外话。如何添加hookportalreferences以requireBabel插件手册