babel 作用+原理+补丁

Posted by CodingWithAlice on July 20, 2021

babel 作用+原理+补丁

总结:

  • 作用:已知 babel 用于将 es6 语法转换成浏览器普遍支持的 es5 语法,使开发能够使用便捷的 es6 进行开发
  • 工作原理:先将 ES6 源码转换为 AST,然后再将 ES6 语法的 AST 转换为 ES5 语法的 AST,最后利用 ES5 的 AST 生成 JavaScript 源代码
    • 解析(Parsing-@babel/parser):词法分析+语法分析得到 AST
    • 转换(Transformation-@babel/traverse):遍历 AST 并转换(ES6的AST -> ES5的AST)
    • 生成(Code Generation-@babel/generator):根据转换后的 AST 转换成 js 代码
  • Polyfill:但是babel只对es6语法进行转换,比如将箭头函数编译成函数形式,但是 不会增加或修改原有的属性和方法,比如 IteratorGeneratorSetMapsProxyReflectSymbolPromise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。如果要在低版本的浏览器中执行es6的方法,就需要 对ES6函数进行补充,安装并在页面引入 @babel/polyfill

参考文章:一口(很长的)气了解 babel深入Babel,这一篇就够了

核心要点记录

  • babel 总共分为三个阶段

    • 解析 @babel/parser

      通过 babyIon(7.x改名为@babel/parser)实现:先 词法分析 把字符串形式的代码解析为 令牌tokens 流 (类似 AST 中节点),再 语法分析 把令牌流转换成 AST

    • 转换 @babel/traverse

      接收到 AST 并通过 @babel/traverse (维护了 AST 的状态,定义了节点的增删改方法)进行深度优先遍历

    • 生成 @babel/generator

      将 AST 通过 @babel/generator 进行深度优先遍历,构建字符串,转换成 js 代码

      1.jpg

  • babel 本身不具有任何转化功能 - 功能全部集成在 plugin

    • 语法插件 - 在【解析】阶段解析更多语法
    • 转译插件 - 在【转换】阶段进行源码转换

preset

  • es2015 (单点)和 preset (套餐)的差别:
    • es2015 - 一套规范,包含大概十几二十个转译插件
    • preset - 插件的集合,不必重复定义、安装

分类:

  • 1/2、官方内容,目前包括 env(最重要), react, flow, minify

  • 2/2、stage-x,这里面包含的都是当年最新规范的草案,每年更新

    低一级的 stage 会包含所有高级 stage 的内容,例如 stage-1 会包含 stage-2, stage-3 的所有内容。

    • Stage 0 - 稻草人: 只是一个想法,经过 TC39 成员提出即可
    • Stage 1 - 提案: 初步尝试
    • Stage 2 - 初稿: 完成初步规范
    • Stage 3 - 候选: 完成规范和浏览器初步实现
    • Stage 4 - 完成: 将被添加到下一年度发布 - 在下一年更新会直接放到 env 中,所以没有单独的 stage-4 可供使用

Babel 7.x 变更淘汰 es201x,删除 stage-x,强推 env (重点)

执行顺序

  • Plugin 会运行在 Preset 之前
  • Plugin 会从前到后顺序执行
  • Preset 的顺序则 刚好相反 (从后向前) - 只要按照规范的时间顺序列出即可,例如:['es2015', 'stage-0']

插件/preset的配置项

带了配置项,自己变成数组;不带配置项,直接列出名字

"presets": [
    // 带了配置项,自己变成数组
    [
        "env", // 第一个元素依然是名字
        // 第二个元素是对象,列出配置项
        {
            "module": false
        }
    ],
    // 不带配置项,直接列出名字
    "stage-2",
]

env

  • 核心目的是通过配置得知目标环境的特点,然后 只做必要的转换

  • 配置项 - 如果不写任何配置项,env 等价于 latest

      "presets": [
          [
              "env", 
              {
                  // 常见配置项 targets
                  "targets": {
                      // 考虑所有浏览器的最新2个版本(safari大于等于7.0版本)特性,将必要的代码进行转换
                      "browsers": ["last 2 versions", "safari >= 7"],
      				// 指定需要支持node 6.10 及以上的版本                
                      "node": "6.10",
                      // 指定需要兼容的浏览器
                      "ie": "11",
                      "chrome": "58",
                      // 指定只需要处理支持 ES 模块的浏览器 - 浏览器字段被忽略
                      "esmodules": true,
                  }
              }
          ]
      ]
    

Babel 7.x 变更

1、preset 变更:淘汰 es201x,删除 stage-x,强推 env (重点)

2、npm package 名称的变化 (重点):把所有 babel-* 重命名为 @babel/*

babel-cli —> @babel/cli;

babel-preset-env —> @babel/preset-env 也可以简写为 @babel/env;

babel-plugin-transform-arrow-functions —> @babel/plugin-transform-arrow-functions 也可以简写为 @babel/transform-arrow-functions

babel 解析语法的内核 babylon 现在重命名为 @babel/parser

3、不再支持低版本 node,要求 nodejs >= 6