Babel
作用
语法转换
通过 Polyfill 方式在目标环境中添加缺失的特性 (通过 @babel/polyfill 模块)
@babel/preset-env
@babel/preset-env
一系列插件的集合,提供代码转换功能,需配合
Polyfill
或core-js
来提供一些兼容的特性根据
browserslist
的配置来指定支持的浏览器环境{ "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] }
Polyfill
Polyfill
Babel 7.4.0
以上弃用@babel/polyfill
包括了core-js
和regenerator runtime
来模拟完整的ES2015+环境,并添加到了全局作用域直接使用
core-js/stable
和regenerator-runtime/runtime
来取代两种引入方式都可
import "@babel/polyfill";
// webpack module.exports = { entry: ["@babel/polyfill", "./app/js"], };
缺点:完整引入,包括了兼容所有低版本的代码
优化:通过在
.babelrc
中配置useBuiltIns
参数{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "entry", // 根据环境需要引入不同的core-js(target参数可指定环境),需手动提前引入@babel/polyfill或core-js "useBuiltIns": "usage", // 在需要兼容的每个文件中引入需要的补丁(一个bunlder只会加载一次相同的补丁),无需手动引入 "useBuiltIns": false, // 或未指定,需手动添加到webpack entry数组中 "spec": true, // 为此预设中支持它们的插件启用更多符合规范但可能较慢的转换。不常用 "loose": true // false更符合ES6规范,true更符合ES5风格,速度快兼容性好 } ] ] }
transform-runtime
transform-runtime
重用
babel
注入的辅助代码安装
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
目的
babel
使用了一些包含通用函数的辅助代码比如_extend
,这些代码默认会被添加到每一个需要它的文件中,这是不必要的。@babel/plugin-transform-runtime
插件会让所有的辅助代码引用@babel/runtime
模块来避免重复。@babel/runtime
会被编辑到包中。直接引入
@babel/polyfill
或core-js
例如Promise、Set、Map,会污染全局作用
配置
// 没有选项 { "plugins": ["@babel/plugin-transform-runtime"] } // 有选项(都是默认值) { "plugins": [ [ "@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": false, "helpers": true, "regenerator": true, "useESModules": false, "version": "7.0.0-beta.0" } ] ] }
技术细节
当使用
generators/async
函数时,自动requires @babel/runtime/regenerator
(可通过regenerator选项更改)如有必要可使用
core-js
替代polyfill
(可通过corejs
选项更改)自动删除嵌入的辅助代码,使用
@babel/runtime/helpers
模块来替代
实现方式:创建别名函数而不是是定义到全局上
Regenerator
function* foo() {} //转换后 "use strict"; var _regenerator = require("@babel/runtime/regenerator"); var _regenerator2 = _interopRequireDefault(_regenerator); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var _marked = [foo].map(_regenerator2.default.mark); function foo() { return _regenerator2.default.wrap( function foo$(_context) { while (1) { switch ((_context.prev = _context.next)) { case 0: case "end": return _context.stop(); } } }, _marked[0], this ); }
core-js
var sym = Symbol(); var promise = Promise.resolve(); var check = arr.includes("yeah!"); console.log(arr[Symbol.iterator]()); // 转换后 import _getIterator from "@babel/runtime-corejs3/core-js/get-iterator"; import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes"; import _Promise from "@babel/runtime-corejs3/core-js-stable/promise"; import _Symbol from "@babel/runtime-corejs3/core-js-stable/symbol"; var sym = _Symbol(); var promise = _Promise.resolve(); var check = _includesInstanceProperty(arr).call(arr, "yeah!"); console.log(_getIterator(arr));
实例方法例如
"foobar".includes("foo")
在corejs: 3
中才有效Helper
class Person {} // 普通转换:辅助代码会被添加到每个需要的文件中 "use strict"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Person = function Person() { _classCallCheck(this, Person); }; // 使用runtime转换后 "use strict"; var _classCallCheck2 = require("@babel/runtime/helpers/classCallCheck"); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var Person = function Person() { (0, _classCallCheck3.default)(this, Person); };
Last updated
Was this helpful?