Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

简介与用法

1. 简介

  • 本质就是编译器,是一个工具集

    • 版本
      • 通常指@babel/core这个包的版本
      • 目前较新的是Babel7,一律放在@babel这个域下面
      • 较旧的 Bebel6,则没有域的概念,是 babel-core 这种独立包
  • 作用

    • 把 ECMAScript 2015(ES6)及以后的代码 转变成 ES5 代码,兼容低版本的浏览器
    • 包括两部分工作
      • (一)语法转换(通过 AST 树抽象 实现)
      • (二)补齐 API(通过 Polyfill 垫片 实现)
        • 包括 Promise.resolve、Object.assign 等 新全局方法
        • 包括 .find、.fill 等 新实例方法

2. 基础用法——语法转换

  • 安装 babel 相关包

    npm i -D @babel/cli @babel/core @babel/preset-env
    
    • @babel/cli
      • 命令行工具
    • @babel/core
      • 核心底层依赖包
    • @babel/preset-env
      • 提供了 ES6 转 ES5 的语法规则
      • 包含了 babel-preset-latest 的功能,并对其进行增强
    • 其他可能用到的
      @babel/preset-react
      
      • 用于处理转换 react 的 jsx 文件
        @babel/preset-typescript
        
      • 用于处理转换 ts 文件,以及 tsx 文件
  • 设置配置文件babel.config.js(或.babelrc.js

    module.exports = {
      presets: ["@babel/env"],
      plugins: [],
    };
    
    • (不推荐)也可以使用.babelrc
      {
        "presets": ["@babel/env"],
        "plugins": []
      }
      
    • (不推荐)也可以直接写到package.json
      "babel": {
          "presets": ["@babel/env"],
          "plugins": []
      }
      
    • 总结起来,就是配置presetsplugins这俩,填入的是 预设 npm 包名 或者 插件 npm 包名,就算是在 webpack 的 babel-loader 中也是这样
      • 插件的作用
        • 可自由地进行插件开发,对代码做不同的处理,目前插件有 90 多个
        • 大多都整合到预设@babel/preset-env@babel/preset-react里面了
        • 单独用的插件,可能也就@babel/plugin-transform-runtime这种
      • 预设的作用
        • 内含一组常规的插件集合,开箱即用,避免手写大量插件名
    • 处理的先后顺序
      • 插件比预设先执行
      • 插件执行顺序是插件数组从前向后执行
      • 预设执行顺序是预设数组从后向前执行
  • 新建一个main.js文件,写入 ES6 代码

    let func = (num) => num + 1;
    
  • 执行命令,编译成 ES5 代码

    npx babel main.js -o main_es5.js
    
    • 此 npx 命令等价于
      node_modules/.bin/babel main.js -o main_es5.js
      
  • 检查新生成的main_es5.js文件

    "use strict";
    let func = function func(num) {
      return num + 1;
    };
    
    • 转化之后默认是严格模式

3. 基础用法——补齐 API

最古老的补齐方式

网站内引入 polyfill.js 脚本

<script src="https://cdn.bootcss.com/babel-polyfill/7.6.0/polyfill.js"></script>

现代化方式

  • 安装 babel 相关包

    npm i -S @babel/polyfill
    
    • 这个包实际包含core-jsregenerator-runtime这两个依赖,更推荐换成安装这俩并引入,因为 polyfill 内部的 core-js 是 2.x 版本,而 core-js 已经发布到 3.x 版本,会更好用
      npm i -S core-js regenerator-runtime
      
  • 安装 webpack 开发依赖

    npm i -D webpack webpack-cli
    
  • 新建一个main.js文件,并写入 ES6 代码,作为入口文件

    var promise = Promise.resolve("ok");
    console.log(promise);
    
    • 【可选方式 1,不推荐】在第一行加入import '@babel/polifill';
    • 【可选方式 2,推荐】更改webpack.config.js
      const path = require("path");
      module.exports = {
        entry: ["@babel/polyfill", "./main.js"],
        output: {
          filename: "main_es.js",
          path: path.resolve(__dirname, ""),
        },
        mode: "development",
      };
      
    • 【可选方式 3,更推荐】更改webpack.config.js
      const path = require("path");
      module.exports = {
        entry: ["core-js/stable", "regenerator-runtime/runtime", "./main.js"],
        output: {
          filename: "main_es.js",
          path: path.resolve(__dirname, ""),
        },
        mode: "development",
      };
      
  • 执行 webpack 打包命令;

    npx webpack main.js -o main_es5.js
    
  • 缺点

    • 把整个 polyfill 文件引入,会非常大,影响页面加载时间,所以要用下面的高级用法

4. @babel/env 不配参

@babel/env没有配置参数

  • 需要配置browserslist目标环境,从里面读取规则,尽量少做转换
    • 可以在 package.json 内直接配置
      "browserslist": [
          "chrome 38",
          "ie 11"
      ]
      
      • 代表向下兼容到 chrome38 版本
    • 也可以在根目录下新建 .browserslistrc 文件配置
      chrome 38
      ie 11
      
  • 如果连browserslist都没有配置,就会全部进行转换

5. @babel/env 配参

@babel/env配置参数

module.exports = {
  presets: [
    [
      "@babel/env",
      {
        //参数
      },
    ],
  ],
  plugins: [],
};

四个常用参数

  • target(不推荐)

    targets: {
        "chrome": "38",
        "ie": "11"
    }
    
    • 如果配置了这个,就会忽略 browserslist 的配置,这样不好
  • useBuiltIns(推荐)

    useBuiltIns: "usage";
    
    • 可以根据实际使用到的 API,进行这部分的 polyfill
    • 不需要在 entry 入口项中书写文件
    • 另外两个取值
      • false 默认,会全部引入
      • entry 会针对向下兼容的程度,进行补全,就算没用到的也补上
  • corejs(推荐)

    corejs: 3;
    
    • 使用新的 corejs 3 版本进行补齐
  • modules(推荐)

    modules: "false";
    
    • 不对 ES6 模块化的 import 引入方式做更改
    • 另外的取值
      • auto 默认,会把 import 全部改成 require

6. plugin-transform-runtime

使用@babel/runtime-corejs3@babel/plugin-transform-runtime

  • 作用
    • 一次性注入 每个文件转化成 ES5 后 重复的函数声明,减少体积,对应例子【1】
    • 避免 注入导致的全局环境污染(因为 polyfill 默认是通过重写 window 下的对象来实现的),通过内置对象重命名实现
  • 例子
    • 【1】当语法转换后,多个文件内出现重复的内联辅助函数(inline Babel helpers),会自动引入@babel/runtime/helpers 里的辅助函数来替代;
    • 【2】当代码里使用了 core-js 的 API,自动引入@babel/runtime-corejs3/core-js-stable/,以此来替代全局引入的 core-js/stable;
    • 【3】当代码里使用了 Generator/async 函数,自动引入@babel/runtime/regenerator,以此来替代全局引入的 regenerator-runtime/runtime;
  • 安装
    npm i -S @babel/runtime-corejs3
    
    • 这个包是@babel/runtime 的进化版,在辅助函数的基础上(作用 1),添加了 API 转换函数(作用 2)
    npm i -D @babel/plugin-transform-runtime
    
  • 简单使用
    {
        "presets": [
            "@babel/env"
        ],
        "plugins": [
            "@babel/plugin-transform-runtime"
        ]
    }
    
    • 如果使用了这种方式
      • 就不要再用上面基础用法引入 polyfill 了
  • 加参数使用
    • 默认不加参,等价于如下配置
      {
         "presets": [
             "@babel/env"
         ],
         "plugins": [
             ["@babel/plugin-transform-runtime". {
                 "helpers": true,
                 "corejs": false,
                 "regenerator": true,
                 "useESModules": false,
                 "absoluteRuntime": false,
                 "version": "7.0.0-beta.0"
             }]
         ]
      }
      
      • helpers 即辅助函数,默认开启
      • corejs 是否做 API 转换,默认关闭
        • 只有在开发 NPM 包的时候,才开启,取值 2 或者 3,指明 core-js 版本,避免使用者与自己的版本有冲突
        • 自己做项目,不需要开
      • regenerator 是否做 async/generater 转换,默认开启
        • 因为转换代码较少,就直接打开了
      • useESModules,是否使用 ES6 模块,默认 false
        • 在使用 webpack 一类的打包工具时,可以设为 true,做静态分析和 tree shaking