babel-runtime和babel-polyfill两者区别优缺点
先说两种方式的原理:
babel-polyfill 使用场景
Babel 默认只转换新的 JavaScript 语法,而不转换新的 API。例如,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转译。如果想使用这些新的对象和方法,必须使用 babel-polyfill,为当前环境提供一个垫片。它不会将代码编译成低版本的ECMAScript,他的原理是当运行环境中并没有实现的一些方法,babel-polyfill中会给做兼容
babel-runtime使用场景
将es6编译成es5去运行,前端可以使用es6的语法来写,最终浏览器上运行的是es5,Babel 转译后的代码要实现源代码同样的功能需要借助一些帮助函数,例如,{ [name]: 'JavaScript' } 转译后的代码如下所示
'use strict';
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var obj = _defineProperty({}, 'name', 'JavaScript');
类似上面的帮助函数 _defineProperty 可能会重复出现在一些模块里,导致编译后的代码体积变大。Babel 为了解决这个问题,提供了单独的包 babel-runtime 供编译模块复用工具函数。
启用插件 babel-plugin-transform-runtime 后,Babel 就会使用 babel-runtime 下的工具函数,转译代码如下:
'use strict';
// 之前的 _defineProperty 函数已经作为公共模块 `babel-runtime/helpers/defineProperty` 使用
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var obj = (0, _defineProperty3.default)({}, 'name', 'JavaScript');
除此之外,babel 还为源代码的非实例方法(Object.assign,实例方法是类似这样的 "foobar".includes("foo"))和 babel-runtime/helps 下的工具函数自动引用了 polyfill。这样可以避免污染全局命名空间,非常适合于 JavaScript 库和工具包的实现。例如 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
});
优缺点:
babel-polyfill:通过向全局对象和内置对象的prototype上添加方法来实现,比如运行环境中不支持Array-prototype.find,引入polyfill,前端就可以放心的在代码里用es6的语法来写;但是这样会造成全局空间污染。比如像Array-prototype.find就不存在了,还会引起版本之前的冲突。不过即便是引入babel-polyfill,也不能全用,代码量比较大。
babel-runtime:不会污染全局对象和内置的对象原型。比如当前运行环境不支持promise,可以通过引入babel-runtime/core-js/promise来获取promise,或者通过babel-plugin-transform-runtime自动重写你的promise。但是它不会模拟内置对象原型上的方法,比如Array-prototype.find,就没法支持了,如果运行环境不支持es6,代码里又使用了find方法,就会出错,因为es5并没有这个方法。
transform-runtime只会对es6的语法进行转换,而不会对新api进行转换。
如果需要转换新api,就要引入babel-polyfill.
思考:babel-runtime 为什么适合 JavaScript 库和工具包的实现?
避免 babel 编译的工具函数在每个模块里重复出现,减小库和工具包的体积;
在没有使用 babel-runtime 之前,库和工具包一般不会直接引入 polyfill。否则像 Promise 这样的全局对象会污染全局命名空间,这就要求库的使用者自己提供 polyfill。这些 polyfill 一般在库和工具的使用说明中会提到,比如很多库都会有要求提供 es5 的 polyfill。在使用 babel-runtime 后,库和工具只要在 package.json 中增加依赖 babel-runtime,交给 babel-runtime 去引入 polyfill 就行了;
总结:
具体项目还是需要使用 babel-polyfill,只使用 babel-runtime 的话,实例方法不能正常工作(例如
"foobar".includes("foo"));JavaScript 库和工具可以使用 babel-runtime,在实际项目中使用这些库和工具,需要该项目本身提供 polyfill;
疑问:像 antd@2.x 这样的库使用了 babel-runtime,在实际项目中使用 antd@2.x,我们需要引入 babel-polyfill。但全部 polyfill 打包压缩下来也有 80kb 左右,其中很多 polyfill 是没有用到的,如何减少体积呢?手工一个个引入使用到的 polyfill,似乎维护成本太高!
babel-runtime和babel-polyfill两者区别优缺点的更多相关文章
- @babel/runtime 和 @babel/plugin-transform-runtime 两个的作用是什么
Babel 最基础的功能就是将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中. 最基础的依赖包也就是 ...
- Install fail! Error: [@@babel/runtime/core-js/object/keys]
1.Install fail! Error: [@@babel/runtime/core-js/object/keys] "@babel/runtime": "7.0.0 ...
- Error: Cannot find module '@babel/runtime/core-js/object/keys'(npm start报错)
1.问题描述: 在npm start启动react项目的时候,会出现Cannot find module '@babel/runtime/core-js/object/keys'的报错: 打开:项目根 ...
- Module not found: Error: Can't resolve '@babel/runtime/helpers/classCallCheck' and Module not found: Error: Can't resolve '@babel/runtime/helpers/defineProperty'
These two mistakes are really just one mistake, This is because the following file @babel/runtime ca ...
- Babel插件:@babel/plugin-transform-runtime
一 概述 每个Babel编译后的脚本文件,都以导入的方式使用Babel的帮助函数,而不是每个文件都复制一份帮助函数的代码. 1 优点 (1)提高代码重用性,缩小编译后的代码体积. (2)防止污染全局作 ...
- 【Babel】293- 初学 Babel 工作原理
戳蓝字「前端技术优选」关注我们哦! 前言 babel Babel 对于前端开发者来说应该是很熟悉了,日常开发中基本上是离不开它的. 已经9102了,我们已经能够熟练地使用 es2015+ 的语法.但是 ...
- SVN和Git 介绍,区别,优缺点以及适用范围
SVN是Subversion的简称,是一个开放源代码的版本控制系统,支持大多数常见的操作系统.作为一个开源的版本控制系统,Subversion管理着随时间改变的数据.这些数据放置在一个中央资料档案库( ...
- OLEDB和ODBC的区别(优缺点)
ODBC是一种连接数据库的开放标准,OLEDB(对象链接和嵌入数据库)位于ODBC层与应用程序之间. 在你的ASP页面里,ADO是位于OLEDB之上的应用程序. 你的ADO调用先被送到OLEDB,然后 ...
- xml与json的原理,区别,优缺点.
1.定义介绍 (1).XML定义扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许 ...
随机推荐
- 洛谷 [P1426] 通往奥格瑞玛的道路
题目中的表述很明显是一道二分答案+最短路的题目,二分收取的费用x判断能否到达奥格瑞玛.检验函数用SPFA跑最短路,注意,费用高于x的点不能使用. #include <iostream> # ...
- BZOJ 1801: [Ahoi2009]chess 中国象棋 [DP 组合计数]
http://www.lydsy.com/JudgeOnline/problem.php?id=1801 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放 ...
- LeetCode - 626. Exchange Seats
Mary is a teacher in a middle school and she has a table seat storing students' names and their corr ...
- ionic2+Angular 使用HttpInterceptorService拦截器 统一处理数据请求
sstep1:新建http-Interceptor.ts文件 import { Injectable } from '@angular/core'; import { HttpInterceptorS ...
- 当inline元素包裹block元素时会发生什么
经常有图片链接写法如下: <a href="www.baidu.com"><img src="baidu.jpg" /></a&g ...
- 搭建简易的c语言与python语言CGI和Apache服务器的开发环境
搭建简易的c语言CGI和Apache服务器的开发环境 http://www.cnblogs.com/tt-0411/archive/2011/11/21/2257203.html python配置ap ...
- mysql 获取上个月,这个月的第一天或最后一天
/*上个月今天的当前时间*/select date_sub(now(),interval 1 month) /*上个月今天的当前时间(时间戳)*/select UNIX_TIMESTAMP(date_ ...
- memcached 的实践操作
memcached安装和使用 yum install -y libevent memcached libmemcached 启动命令: /etc/init.d/memcached st ...
- 【netty这点事儿】ByteBuf 的使用模式
堆缓冲区 最常用的 ByteBuf 模式是将数据存储在 JVM 的堆空间中. 这种模式被称为支撑数组(backing array), 它能在没有使用池化的情况下提供快速的分配和释放. 直接缓冲区 直接 ...
- windows上nginx的安装和配置
http://www.cnblogs.com/Li-Cheng/p/4399149.html http://www.cnblogs.com/huayangmeng/archive/2011/06/15 ...