简介与用法
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 文件
- 用于处理转换 react 的 jsx 文件
-
设置配置文件
babel.config.js(或.babelrc.js)module.exports = { presets: ["@babel/env"], plugins: [], };- (不推荐)也可以使用
.babelrc{ "presets": ["@babel/env"], "plugins": [] } - (不推荐)也可以直接写到
package.json"babel": { "presets": ["@babel/env"], "plugins": [] } - 总结起来,就是配置
presets和plugins这俩,填入的是 预设 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
- 此 npx 命令等价于
-
检查新生成的
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-js与regenerator-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.jsconst path = require("path"); module.exports = { entry: ["@babel/polyfill", "./main.js"], output: { filename: "main_es.js", path: path.resolve(__dirname, ""), }, mode: "development", }; - 【可选方式 3,更推荐】更改
webpack.config.jsconst 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", };
- 【可选方式 1,不推荐】在第一行加入
-
执行 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
- 可以在 package.json 内直接配置
- 如果连
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
- 默认不加参,等价于如下配置