Open AnnVoV opened 6 years ago
参考资料: 1.babel到底将代码转换成什么鸟样? https://github.com/lcxfs1991/blog/issues/9 2.babel 在线编译器 https://www.babeljs.cn/repl 3.你真的会用babel 吗? https://github.com/sunyongjian/blog/issues/30
Node's module.exports 与 ES6 的export default 的区别是什么?如果想在Node中使用es6 的模块写法如何做到?
'use strict' class Animal { constructor(name) { this.name = name; } sayName() { return `My name is ${this.name}`; } } module.exports = Animal; // 这样写就不行 export default Animal;
1.Node.js 中并不支持es6的语法,所以需要借助babel这 种工具将es6 的module转换为CommonJs(babel转换后的代码是遵循commonJs规范的) 【拓展】: es6 经过babel 转换得到了遵循CommonJs的es5, 借助webpack(webpack本身也遵循CommonJs规范) 打包工具,生成能在浏览器中运行的es5代码 那babel 把es6 转换为commonJs 本质底层做了什么呢?
// input export const foo = 42; export default 21; // output 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var foo = exports.foo = 42; exports.default = 21;
(1)我们看到在exports 对象上添加了__esModule 属性值为true来标记是否经过了babel的处理 (2)我们看到default 变成了exports的一个属性
import bar from './input' console.log(bar)
babel 将会转换为下面的代码
var _input = require('./input') var _input2 = _interoRequireDefault(_input); function _interoRequireDefault(obj) { return obj && obj.__esModule?obj:{default: obj}; } console.log(_input2.default);
最终我们看到import 的内容都是挂在default上的
参考资料: 1.探索babel和babel插件是怎么工作的 https://segmentfault.com/a/1190000013261724#articleHeader2 2.Babylon AST node types https://github.com/babel/babylon/blob/master/ast/spec.md#variabledeclaration 3.深入理解Babel原理及其使用,babel把es6转换成es5的原理是什么?(重要) http://www.fly63.com/article/detial/197 4.Understanding ASTs by Building Your Own Babel Plugin https://www.sitepoint.com/understanding-asts-building-babel-plugin/ 5.AST Explorer https://astexplorer.net/ 6.babylon 文档 https://github.com/babel/babylon/blob/master/ast/spec.md#variabledeclaration
如果是以命令行方式使用babel,那么babel的设置就以命令行参数的形式带过去; 还可以在package.json里在babel字段添加设置; 但是建议还是使用一个单独的.babelrc文件,把babel的设置都放置在这里,所有babel API的options(除了回调函数之外)都能够支持,具体的options见babel的API options文档
ES6代码输入 ==》 babylon进行解析 ==》 得到AST ==》 plugin用babel-traverse对AST树进行遍历转译 ==》 得到新的AST树 ==》 用babel-generator通过AST树生成ES5代码 (即分为 parsing --> transforming --> generating 三个阶段)
重点参考了这篇文章: https://segmentfault.com/a/1190000013261724#articleHeader2
我们写插件,主要就是利用babel在遍历AST树的过程中提供的钩子,来改造AST去执行我们想要的函数
babel 为我们提供了一个visitor对象,通过visitor对象,我们可以访问到我们代码的任何一个部分。visitor在遍历到对应节点执行对应函数时候会给我们传入path参数,path参数是表示两个节点之间连接的对象,而不是当前节点 看下面这个例子,我们要写一个插件,把代码中的log替换为console.log
visitor
path参数
const code = ` const a = 3 * 103.5 * 0.8 log(a) const b = a + 105 - 12 log(b) ` const visitor = { CallExpression(path) { // 这里判断一下如果不是log的函数执行语句则不处理 if (path.node.callee.name !== 'log') return // t.CallExpression 和 t.MemberExpression分别代表生成对于type的节点,path.replaceWith表示要去替换节点,这里我们只改变CallExpression第一个参数的值,第二个参数则用它自己原来的内容,即本来有的参数 path.replaceWith(t.CallExpression( t.MemberExpression(t.identifier('console'), t.identifier('log')), path.node.arguments )) } } const result = babel.transform(code, { plugins: [{ visitor: visitor }] }) console.log(result.code)
讲解几个函数: 1.CallExpression 是执行函数时的钩子 2.通过path.node.callee.name 来获取当前函数是否是需要去处理的函数 3.t.MemberExpression 是获取某个对象的属性比如t.identifier('console'), t.identifier('log') 就是获取console.log (我自己感觉,babel-types的api 还是要再看看,才能写好一个babel插件)
t.identifier('console'), t.identifier('log')
console.log
剖析Babel -- Babel 总览 http://www.alloyteam.com/2017/04/analysis-of-babel-babel-overview/
参考资料: 1.babel到底将代码转换成什么鸟样? https://github.com/lcxfs1991/blog/issues/9 2.babel 在线编译器 https://www.babeljs.cn/repl 3.你真的会用babel 吗? https://github.com/sunyongjian/blog/issues/30
背景
Node's module.exports 与 ES6 的export default 的区别是什么?如果想在Node中使用es6 的模块写法如何做到?
例子
解释
1.Node.js 中并不支持es6的语法,所以需要借助babel这 种工具将es6 的module转换为CommonJs(babel转换后的代码是遵循commonJs规范的) 【拓展】: es6 经过babel 转换得到了遵循CommonJs的es5, 借助webpack(webpack本身也遵循CommonJs规范) 打包工具,生成能在浏览器中运行的es5代码 那babel 把es6 转换为commonJs 本质底层做了什么呢?
当 export 文件时
(1)我们看到在exports 对象上添加了__esModule 属性值为true来标记是否经过了babel的处理 (2)我们看到default 变成了exports的一个属性
当 import 文件时
babel 将会转换为下面的代码
最终我们看到import 的内容都是挂在default上的
拓展深入babel
参考资料: 1.探索babel和babel插件是怎么工作的 https://segmentfault.com/a/1190000013261724#articleHeader2 2.Babylon AST node types https://github.com/babel/babylon/blob/master/ast/spec.md#variabledeclaration 3.深入理解Babel原理及其使用,babel把es6转换成es5的原理是什么?(重要) http://www.fly63.com/article/detial/197 4.Understanding ASTs by Building Your Own Babel Plugin https://www.sitepoint.com/understanding-asts-building-babel-plugin/ 5.AST Explorer https://astexplorer.net/ 6.babylon 文档 https://github.com/babel/babylon/blob/master/ast/spec.md#variabledeclaration
babel的包构成
核心包
功能包
工具包
babel 配置
如果是以命令行方式使用babel,那么babel的设置就以命令行参数的形式带过去; 还可以在package.json里在babel字段添加设置; 但是建议还是使用一个单独的.babelrc文件,把babel的设置都放置在这里,所有babel API的options(除了回调函数之外)都能够支持,具体的options见babel的API options文档
babel 工作原理
ES6代码输入 ==》 babylon进行解析 ==》 得到AST ==》 plugin用babel-traverse对AST树进行遍历转译 ==》 得到新的AST树 ==》 用babel-generator通过AST树生成ES5代码 (即分为 parsing --> transforming --> generating 三个阶段)
如何写一个babel 插件
重点参考了这篇文章: https://segmentfault.com/a/1190000013261724#articleHeader2
我们写插件,主要就是利用babel在遍历AST树的过程中提供的钩子,来改造AST去执行我们想要的函数
babel 为我们提供了一个
visitor
对象,通过visitor对象,我们可以访问到我们代码的任何一个部分。visitor
在遍历到对应节点执行对应函数时候会给我们传入path参数
,path参数
是表示两个节点之间连接的对象,而不是当前节点 看下面这个例子,我们要写一个插件,把代码中的log替换为console.log讲解几个函数: 1.CallExpression 是执行函数时的钩子 2.通过path.node.callee.name 来获取当前函数是否是需要去处理的函数 3.t.MemberExpression 是获取某个对象的属性比如
t.identifier('console'), t.identifier('log')
就是获取console.log
(我自己感觉,babel-types的api 还是要再看看,才能写好一个babel插件)好文推荐
剖析Babel -- Babel 总览 http://www.alloyteam.com/2017/04/analysis-of-babel-babel-overview/