一、前言
-
babel 的核心功能是转译代码(新语法,如箭头函数,类等)和polyfill能力(新内置对象,api等),本文主要讨论polyfill能力。
-
babel7.4之后,官方已经废弃@babel/polyfill 。@babel/runtime 在7.0.0后也去除了polyfill能力的core-js。polyfill作为前端垫片,铺平各浏览器差异的类库,前端开发者该何去何从,如何选择呢
二、babel-polyfill 、babel-runtime、 babel/preset-env
1、babel-polyfill
它的初衷是模拟(emulate)一整套 ES2015+ 运行时环境,所以它的确会以全局变量的形式 polyfill Map、Set、Promise 之类的类型,也的确会以类似 Array.prototype.includes() 的方式去注入污染原型
优点:
1、解决了Babel不转换新api的问题,能解决runtime无法转换内置对象新的实例方法。
缺点:
1、在代码中插入帮助函数,污染了全局环境。引入新的全局对象,修改了原型方法。
2、不同文件中存在重复代码,,编译后体积较大。
举个例子, 我在项目中定义了跟规范不一致的Array.from()函数,同时引入了一个库(依赖babel-polyfill),此时,这个库可能覆盖了自定义的Array.from()函数,导致出错。 这就是babel-runtime存在的原因。它将开发者依赖的全局内置对象等,抽取成单独的模块,并通过模块导入的方式引入,避免了对全局作用域的修改(污染)。
const obj = {}
Object.assign(obj, { age: 30 });
//转译后
'use strict';
// 使用了 core-js 提供的 assign
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var obj = {};
(0, _assign2.default)(obj, {
age: 30
});
2、babel-runtime
此处首先说明的是babel-runtime(babel6) 而不是@babel/runtime(babel7) 在babel 6时代的runtime 包含 工具方法(helper)和polyfill功能core-js,可以通过配置babel-plugin-transform-runtime的属性来决定polyfill能力。
plugins: [
[
"transform-runtime", //babel-plugin-transform-runtime简写
{
"absoluteRuntime": false,
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false,
"version": "7.0.0-beta.0"
}
]
]
babel进入7.0.0后,@babel/runtime的core-js被移除,不在支持polyfill的作用,因此只能提供编译的一些工具方法。垫片能力被放到 @babel/preset-env的 useBuiltIns完成。下文讨论。
本节主要讨论6时代的polyfill的优缺点。
优点:
1)避免了babel-polyfill全局污染
2)结合babel-plugin-transform-runtime的ast分析,实现了内置对象,的静态方法的按需加载。
缺点:
只支持到static方法,全局内置对象等。
babel-polyfill与babel-runtime相比虽然有各种缺点,但在某些情况下仍然不能被babel-runtime替代, 例如, [1, 2, 3].includes(3),Array,Object以及其他”实例”下es6的方法,babel-runtime是无法支持的, 因为babel-runtime只支持到 static 的方法,对于应用项目还需要结合babel-prolyfill使用。 而一些工具库,可以用runtime处理,使用方统一polyfill。
基于此,@babel/preset-env的 useBuiltIns方式 在babel7应用中便诞生了。他继承了babel-runtime不污染全局的特征,并且完善了runtime对原型方法支持不足的缺点。因此是目前应用的主要配置方式。
3、 @babel/preset-env之 useBuiltIns
useBuiltIns影响 编译过程中的polyfill处理,不影响babel调用的插件
false:
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": false, //布尔类型,
"corejs": 3,
"debug": true,
"modules": false
}
]
]
测试结果 babel 不做polyfill转化处理。(不管有没有引入core-js,都不会做polyfill处理) webpack打包依赖import引入,完全按import来
entry
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry",
"corejs": 3,
"debug": true,
"modules": false
}
]
]
需要配合引入
import "core-js"; // 引入es,esnext,以及一些web处理的polyfill
import "core-js/stable"/ /稳定的polyfill
import "core-js/proposals" //提案阶段的polyfill
import "core-js/stage/4.js" // 指定提案级别高的的polyfill
import "regenerator-runtime/runtime"
若不引入core,则不会polyfill 测试结果 Replaced core-js entries with the following polyfills babel会根据import 进行引入polyfill。 优点:在不考虑包大小情况下,引入简单。 缺点: 1)若引入core-js 会引入所有的polyfill,大部分的polyfill都是无用的,包的体积也大大增加了 2)若指定引入细分,则要求开发则对调用的函数,core-js本身要够熟悉,学习成本大,引入难度大。
usage "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3, "debug": true, "modules": false } ] ] 不引入core.js
测试结果: 1、有条件的按需加载(es),esnext不会自动加载,因此使用时一定要注意是不是esnext级别的提案。,
import "core-js/modules/esnext.math.radians.js"; import "core-js/modules/esnext.string.replace-all"; 可以通过node_modules/core-js/modules中查看是不是esnext
2、引不引入corejs,babel结果是一样。
3、esnext手动引入会被webpack进来
三、core2js 、core3js、 es 、esnext
在不传corejs 版本时,corejs默认按core2js获取文件,若安装3.0 ,则会报错,因为core2js、和core3js的文件结构已经发生变化。
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
// "corejs": 2,
"debug": true,
"modules": false
}
]
]
core2js 文件结构
core3js 文件结构
1、 corejs2 es6后提案功能被统一放到core-js/es7中。 目前corejs2,开发分支已经锁死,新特征不再更新完善,所有新提案在core3js上提交。 corejs3 新提案在 core-js/modules/esnext中实现。当 "useBuiltIns": "usage"时,esnext中的方法不会被polyfill,只能手动import。支持ECMAScript稳定功能,引入core-js@3冻结期间的新功能,比如flat
2、加入到ES2016-ES2019中的提案,现在已经被标记为稳定功能
3、更新了提案的实现,增加了proposals配置项,由于提案阶段不稳定,需要谨慎使用
4、增加了对一些web标准的支持,比如URL 和 URLSearchParams
5、现在支持原型方法,同时不污染原型
6、删除了过时的特性
四、总结
@babel/polyfill 由于其污染性,引入不灵活等弊端,babel7.4后已经被官方deprecated。babel-runtime由于其不支持原型方法,还要结合polyfill使用, babel-runtime 在7.0.0后也移除了其polyfill的core-js 。babel7通过预制env 的useBuiltIns配置来实现polyfill。继承了runtime的有点。弥补了原型方法支持不足的问题。
presets: [
["@babel/preset-env", {
useBuiltIns: "entry",
corejs: 3,
}]
]
import "core-js/stable";
import "regenerator-runtime/runtime";
通过corejs 引入后,实现了无污染的polyfill,使用 useBuiltIns: "usage" 可以实现按需加载。
1、脚本
"scripts": {
"clean": "rimraf dist",
"build": "rimraf dist && npx webpack",
"babel": "rimraf babel_result && npx babel src -d babel_result",
"node": "node dist/index.js",
"start": "webpack-dev-server --inline --progress --config webpack.config.js"
},
npm run babel 查看babel 的结果,
"debug": true可以看到babel 构建过程。
- 2、@bebel/*** 类库说明
@babel/runtime //单独的包babel-runtime用以提供编译模块的工具函数,新版本功能被削弱
@babel/plugin-transform-runtime //合并runtime的调用
@babel/preset-env //bebel7 新预制env
@babel/core //babel内核
core-js //polyfill api的差异
regenerator-runtime/runtime // async await yeild iterator等
@babel/polyfill //core-js 和 regenerator-runtime/runtime
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!