babel能够转译ECMAScrIpt2015+的代码,使它能够在旧的浏览器中运行

1. babel工作分为三个部分

  1. 解析:将源代码转换成AST语法树
  2. 转换:将AST语法树进行转换
  3. 生成:将转换后的抽象语法树生成新的源代码

2. 简单实现babel插件

2.1 类转换成普通函数

  1. // babel核心模块
  2. const core = require('@babel/core');
  3. // 同来生成或者判断节点的AST语法树节点
  4. let types = require('@babel/types');
  5. // 官方插件
  6. // let transformClassesPlugins = require('@babel/plugin-transform-classes');
  7. // 自己模拟插件
  8. let transformClassesPlugins = {
  9. visitor: {
  10. ClassDeclaration (path) {
  11. let node = path.node;
  12. let id = node.id;
  13. let methods = node.body.body;
  14. let nodes = [];
  15. methods.forEach(method => {
  16. // 是构造函数
  17. if (methods.kind === 'constructor') {
  18. // types.functionDeclaration 帮我们生成函数节点
  19. let constructorFunction = types.functionDeclaration(
  20. id,
  21. method.params,
  22. method.body
  23. );
  24. nodes.push(constructorFunction);
  25. } else {
  26. // 是普通函数
  27. // 表达式左边
  28. let memberExpression = types.memberExpression(
  29. types.memberExpression(
  30. id,
  31. types.identifier('prototype')
  32. ),
  33. method.key
  34. );
  35. // 表达式右边
  36. let functionExpression = types.functionExpression(
  37. null,
  38. method.params,
  39. method.body
  40. );
  41. // 赋值表达式
  42. let assignmentExpression = types.assignmentExpression(
  43. '=',
  44. memberExpression,
  45. functionExpression
  46. );
  47. nodes.push(assignmentExpression);
  48. }
  49. })
  50. if (nodes.length === 1) {
  51. // 单节点替换
  52. path.replaceWith(nodes[0])
  53. } else {
  54. // 多节点替换
  55. path.replaceWithMultiple(nodes)
  56. }
  57. }
  58. }
  59. };
  60. // 要转换的代码
  61. let sourceCode = `
  62. class Person {
  63. constructor (name) {
  64. this.name = name
  65. }
  66. sayName() {
  67. console.log(this.name)
  68. }
  69. }
  70. `;
  71. let tragetCode = core.transform(sourceCode, {
  72. plugins: [transformClassesPlugins]
  73. });
  74. console.log(tragetCode.code)

2.2 箭头函数转换成普通函数

  1. // babel核心模块
  2. const core = require('@babel/core');
  3. // 同来生成或者判断节点的AST语法树节点
  4. let types = require('@babel/types');
  5. // 官方插件
  6. // let arrowFunctionPlugin = require('babel-plugin-transform-es2015-arrow-functions');
  7. // 模拟官方自定义实现
  8. let arrowFunctionPlugin = {
  9. visitor: {
  10. // 如果是箭头函数表达式,就会进入此函数,,参数是箭头函数的节点路径对象
  11. ArrowFunctionExpression(path) {
  12. let node = path.node;
  13. // 把箭头函数的type改成函数表达式的type
  14. node.type = 'FunctionExpression';
  15. }
  16. }
  17. };
  18. // 要转换的箭头函数
  19. let sourceCode = `
  20. const sum = (a, b) => {
  21. return a + b
  22. }
  23. `;
  24. // 转换抽象语法树
  25. let tragetCode = core.transform(sourceCode, {
  26. plugins: [arrowFunctionPlugin]
  27. });
  28. console.log(tragetCode.code)