摘要:是怎么工作的如何编译应用场景语法糖的代码统一相关概念介绍依赖,提供的方法,只转化语法,不转换类,的基础配置利用对进行劫持,在中进行原理见同时对后的进行缓存,提高下次效率读取缓存根据判断是否需要重新中传入配置入口函数提供
Babel babel是怎么工作的?
parse->AST->transform->gengerate
如何编译js->AST
babel应用场景语法糖的polyfill
代码统一hack
相关概念介绍 babel-polyfill依赖core-js,提供es*->es3的方法,只转化语法,不转换API(类Promise,WeakMap)
babel-helper babel-register(0.7.0-beta)babel的基础配置init
利用pirate对require进行劫持,在hook中进行babel 原理见
同时对babel后的code进行缓存,提高下次babel效率
function compile(code, filename) { ... let cacheKey = `${JSON.stringify(opts)}:${babel.version}`; const env = babel.getEnv(false); if (env) cacheKey += `:${env}`; //读取缓存 根据mtime判断是否需要重新babel if (cache) { const cached = cache[cacheKey]; if (cached && cached.mtime === mtime(filename)) { return cached.code; } } const result = babel.transform(code, { ...opts, sourceMaps: opts.sourceMaps === undefined ? "both" : opts.sourceMaps, ast: false, }); if (cache) { cache[cacheKey] = result; result.mtime = mtime(filename); } if (result.map) { if (Object.keys(maps).length === 0) { installSourceMapSupport(); } maps[filename] = result.map; } return result.code; } //hook中传入ext配置 function hookExtensions(exts) { if (piratesRevert) piratesRevert(); piratesRevert = addHook(compile, { exts, ignoreNodeModules: false }); } //入口函数 export default function register(opts?: Object = {}) { // Clone to avoid mutating the arguments object with the "delete"s below. opts = Object.assign({}, opts); if (opts.extensions) hookExtensions(opts.extensions); if (opts.cache === false && cache) { registerCache.clear(); cache = null; } else if (opts.cache !== false && !cache) { registerCache.load(); cache = registerCache.get(); } ... }babel-core
提供基础的transform方法
如何写一个babel插件babel-plugin其实是对code转出的ast进行操作,
准备工具ast转换工具
ast转换可视化工具
ast的解构可以类比成一个树状或者json嵌套结构,他的每一层结构都可以叫做一个节点,如下图
babel提供一个visitor的方法,允许我们在里面指定我们想要访问的节点,并且可以在命中该节点时做出自定义的的操作
实例分析现在我们有一个需要移除整个业务bundle包里所有console.log的需求
1.那我们首先要知道console.log实际在ast是怎样的一个节点结构
形如
console.log("a")
实际ast的展现如下
对于各个节点具体含义,这里不做细讲,可以参考文末的babel手册
2.这里直接贴上代码讲吧
module.exports = function (babel) { const { types: t, template } = babel; const visitor = { //需要访问的节点名 //访问器默认会被注入两个参数 path(类比成dom),state ExpressionStatement(path, state) { const node = path.node; //延当前节点向内部访问,判断是否符合console解析出的ast的特征 const expressionNode = keyPathVisitor(node, ["expression"]); const isCallExpression = expressionNode.type === "CallExpression"; if (isCallExpression) { const objectName = keyPathVisitor(expressionNode, ["callee", "object", "name"]); const prototypeName = keyPathVisitor(expressionNode, ["callee", "property", "name"]); if (objectName === "console" && prototypeName === "log" && !MAC) { //如果符合上述条件,直接移除该节点 path.remove(); } } } }; return { visitor }; };
3.进阶版:如果我们想在babel-plugin中新增代码呢
差不多有三种方法
A:手动添加节点(很恶心~相信你不会想去了解)
B:先生成ast,直接path.insertBefore
C:使用babel-template
例子: 移除autobind装饰器,并在constructor中自动bind this
1.因为babel判断是否babel是根据modify time,所以babel插件写完想实时生效,需要给当前的env加上 BABEL_DISABLE_CACHE
//babel-register/cache.js function load() { if (process.env.BABEL_DISABLE_CACHE) return; process.on("exit", save); process.nextTick(save); if (!_fs2.default.existsSync(FILENAME)) return; try { data = JSON.parse(_fs2.default.readFileSync(FILENAME)); } catch (err) { return; } }
2.babel插件写完后发布npm时,记得一定要加上babel-plugin-前缀,因为配置在babelrc中的插件名都会被babel在加载时统一加上babel-plugin前缀,然后在模块系统中去查找
题外话 如何实现给require加上hook传送门
参考文献Babel插件手册
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/93618.html
摘要:抽象语法树是怎么生成的谈到这点,就要说到计算机是怎么读懂我们的代码的。需要注意什么状态状态是抽象语法树转换的敌人,状态管理会不断牵扯我们的精力,而且几乎所有你对状态的假设,总是会有一些未考虑到的语法最终证明你的假设是错误的。 现在谈到 babel 肯定大家都不会感觉到陌生,虽然日常开发中很少会直接接触到它,但它已然成为了前端开发中不可或缺的工具,不仅可以让开发者可以立即使用 ES 规范...
摘要:是一个对象,它表示两个节点之间的连接。接着返回一个对象,其属性是这个插件的主要节点访问者。所以上面的执行方式是运行引入了自定义插件的打包文件现在为明显减小,自定义插件成功插件文件目录觉得好玩就关注一下欢迎大家收藏写评论 目录 Babel简介 Babel运行原理 AST解析 AST转换 写一个Babel插件 Babel简介 Babel 是一个 JavaScript 编译器,它能将es...
摘要:我写过一些开源项目,在开源方面有一些经验,最近开到了阮老师的微博,深有感触,现在一个开源项目涉及的东西确实挺多的,特别是对于新手来说非常不友好最近我写了一个,旨在从多方面快速帮大家搭建一个标准的库,本文将已为例,介绍写一个开源库的知识 我写过一些开源项目,在开源方面有一些经验,最近开到了阮老师的微博,深有感触,现在一个开源项目涉及的东西确实挺多的,特别是对于新手来说非常不友好 show...
摘要:本文特此给大家介绍下如何使用配合来构建基于的前端项目。最后,在目录下会生成最终的项目文件。执行单元测试本例中使用进行单元测试。 随着React、Angular2、Redux等前沿的前端框架越来越流行,使用webpack、gulp等工具构建前端自动化项目也随之变得越来越重要。鉴于目前业界普遍更流行使用webpack来构建es6(ECMAScript 2015)前端项目,网上的相关教程也比...
摘要:踩坑入门系列一二添加三目录重构再谈路由陆续更新个人对于脚手架的有一种执念,如果搭建出来就是一个首页标签跳转,实在不是我这个处女座的风格,因此第二步我就想引用框架,相信很多使用的开发者用的也都是这个框架吧。 Next.js踩坑入门系列 (一) Hello Next.js (二) 添加Antd && CSS (三) 目录重构&&再谈路由 陆续更新... 个人对于脚手架的UI有一种执...
阅读 2964·2021-11-23 10:12
阅读 2689·2021-11-23 09:51
阅读 2040·2021-11-15 11:37
阅读 1351·2019-08-30 15:55
阅读 1964·2019-08-29 15:40
阅读 1164·2019-08-28 18:30
阅读 1649·2019-08-28 18:02
阅读 2640·2019-08-26 12:00