Babel 是一个 JS 编译器(输入源码 source code =》 输出编译后的代码 output code)。编译过程分为三个阶段:解析(parsing)、转换(transforming)和打印输出(printing)。
如果没有任何插件,执行 ./node_modules/.bin/babel src --out-dir lib,结果类似于 cont babel = code => code,即代码解析后再输出同样的代码。如果想实现转换(transforming)的功能,我们就需要添加插件。
除了一个个添加插件,我们可以使用预设(a preset)——一系列插件的组合。
代码分析
class A {} // syntax transforms
class B {} // syntax transforms
const p = new Promise((resolve, reject) => {}); // polyfills-supports global variables => core-js@2
Array.from('foo'); // polyfills-supprots static properties =>core-js@2
[1, 2, 3].includes(1); // polyfills-supports instance properties => core-js@3
function* foo() { }; // after syntax transforms,polyfills-supports genetators/async/await functions => regenerator-runtime/runtime
Step1. Syntax transforms
解决这个问题的方法是使用preset——@babel/preset-env。主要功能是根据配置的目标环境(包括浏览器环境和node环境)自动将输入的源码转化为兼容目标环境的代码。
###安装
npm install --save-dev @babel/preset-env
使用
// package.json
{
"browserslist": "> 0.25%, not dead"
}
// .babelrc配置文件
{
"presets": ["@babel/preset-env"]
}
Step2. Polyfills
安装
npm install --save core-js@3
npm install --save regenerator-runtime
###使用
// .babelrc配置文件
{
"presets": [[
"@babel/preset-env", {
"useBuiltIns": "usage", //entry:全部polyfills引入;usage:使用到pollyfills引入
"corejs": 3
}]],
}
Note: useBuiltIns 的默认配置是 false,即不引入pollyfills。useBuiltIns 配置是 entry 时,需要
import "core-js";和import "regenerator-runtime/runtime";在入口文件。useBuiltIns 配置 usage 时,会自动检测代码中用到的功能自动引入模块,当模块未安装,则会报错。
Step3. Problems
问题1:我在项目中定义了跟规范不一致的Promise函数,同时引入了一个库 core-js,这个库可能覆盖自定义的Promise函数,导致出错。优化后我们希望达到的效果,不污染全局和内置对象原型:
// corejs: false
"use strict";
var a = new Promise();
[1, 2, 3].includes(1);
// corejs: 2
"use strict";
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
var a = new _promise["default"]();
[1, 2, 3].includes(1);
// corejs: 3
"use strict";
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));
var _context;
var a = new _promise["default"]();
(0, _includes["default"])(_context = [1, 2, 3]).call(_context, 1);
问题2:多文件时编译生成多次相同的工具函数,例如
// 优化前
class Circle {}
function _classCallCheck(instance, Constructor) {
//...
}
var Circle = function Circle() {
_classCallCheck(this, Circle);
};
// 优化后
var _classCallCheck = require("@babel/runtime/helpers/classCallCheck");
var Circle = function Circle() {
_classCallCheck(this, Circle);
};
如下为解决问题的方法:
安装
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime or npm insall --save @babel/runtime-corejs2 or npm insall --save @babel/runtime-corejs3
Note: 根据个人需要选择材料。
@babel/runtimeis a library that contain's Babel modular runtime helpers and a version ofregenerator-runtime.@babel/runtime-corejs2is a library that contain's Babel modular runtime helpers and a version ofregenerator-runtimeas well ascore-js@2.@babel/runtime-corejs3is a library that contain's Babel modular runtime helpers and a version ofregenerator-runtimeas well ascore-js@3.
使用
//.babelrc配置文件
{
"presets": [[
"@babel/preset-env", {
"useBuiltIns": "usage",
"corejs": 3
}]],
"plugins": [["@babel/plugin-transform-runtime", {"corejs": 3}]]
}