Open creeperyang opened 7 years ago
额,好像现在是习惯性的引入babel-polyfill; 其实关于babel-core这个库,如果使用webpack的话,自然会有babel-loader,但是现在loader又不依赖babel-core,是不是一般都不用加入项目的依赖了
@mengxingshike2012 babel-loader
的 peerDependencies:
"peerDependencies": {
"babel-core": "^6.0.0",
"webpack": "1 || 2 || ^2.1.0-beta || ^2.2.0-rc"
},
我只用了这三个 babel-preset-env + babel-polyfill + whatwg-fetch 。 babel-preset-env很智能的。各种transform傻瓜化配置了。useBuiltIns选项对polyfill也做了筛选,不用引入全部的polyfill
@lgh06 才知道babel-preset-env
👍
是个不错的选择,不过看起来它是依赖指定node版本或者browser版本来决定引入哪些polyfill的;如果不用内置对象原型上的方法,babel-runtime
可能更好一点。
太喜欢Array.from、forEach、Promise,没办法不污染原型了…… 新浏览器里面都内置了,也不能算污染……
有个小问题。比如你引用了一些第三方库,直接require是使用的编译后的文件。但是如果第三方库作者使用了es6并且没有使用相应的polyfill来转换类似于for(item of list) 这种语法转换的时候会变成Symbol。造成某一些环境下对其不支持的错误。这应该是开发者本人来引入polyfill解决还是第三方作者在转换的时候就应该引入polyfill转换?还是说是babel本身的一些问题
@For-me 我觉得是库作者的责任,他应该提供转换后的可用库文件,或者明确告知使用者必须自己转换。
为什么vue-cli生成的项目里,同时使用了transform-runtime
和babel-preset-env
呢
.babelrc:
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
@xwenliang 很好的问题。
我仔细查阅了文档,答案是 babel-preset-env@1.x
没法很好地消除未使用的polyfill(就是说有未使用的代码被引入进来了)。如果希望避免这一点,那么就会禁用useBuiltIns: true
,而用更好的 transform-runtime
代替。
在 babel-preset-env@2.x
中可以用 useBuiltIns: 'usage'
达到按需引入的目的。
详情可见:
https://github.com/babel/babel-preset-env/issues/84
https://github.com/babel/babel-preset-env/pull/241
可以看到 vuejs-templates/webpack/ 引入的是 1.3 的babel-preset-env
。
@creeperyang 专业👍
react不需要同时 用transform-runtime和babel-preset-env ,感觉和vue有关系,或者react里有的工作被babel-preset-react做了
请教作者vue-cli 使用的babel-preset-env 是@1.x ,有不能很好地消除未使用的polyfill的缺点,那么为什么不直接使用transform-runtime而是即使用env又使用runtime,这样重复不会造成打包体积变大吗。并且我没发现vue-cli中有useBuiltIns: true。
@lawpachi 这个可能是应为transform-runtime对实例方法的支持不是很好,所以只只能结合polyfill来进行转码
creeperyang/blog
发自我的 iPhone
在 2018年5月4日,下午7:17,azumia notifications@github.com 写道:
@lawpachi 这个可能是应为transform-runtime对实例方法的支持不是很好,所以只只能结合polyfill来进行转码
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.
Babel 7
及新用法Babel 7
快正式发布了(2018-06-20是@babel/core@^7.0.0-beta.51
),相比6有非常多的更新,这里例举一些主要的,详情可以阅读官方博文。
@babel
scope (防止被占用)babel 的工作流是
输入字符串 -> @babel/parser parser -> AST -> transformer[s] -> AST -> @babel/generator -> 输出字符串
其中在 transformer[s]
阶段,就是使用plugins来转换代码的阶段。不同的plugin转换特定的代码,而preset是一组完成特定转换的plugins,比如babel-preset-es2017
即包含syntax-trailing-function-commas | transform-async-to-generator
两个plugin,用于支持ES2017
的新特性。
plugin 分为 transform plugin(实际转换代码) 和 syntax-plugin(语法支持,即parse阶段),一般transform plugin包含对应的syntax plugin。
以前常用的yearly presets(preset-es2015 | preset-es2016 | preset-es2017
)在 Babel 7 中已经不推荐使用了,建议用 preset-env
代替。我们先跳过 preset-env
(下一节重点讲),来讲一下常用的preset-state-x
presets。
对JS语言的更新需要一个过程(即0-4的stage,过程如下),用于支持这些尚未被加入到标准(如ES5/2016)的更新的presets即preset-state-x
。
The TC39 categorizes proposals into the following stages:
- Stage 0 - Strawman: just an idea, possible Babel plugin.
- Stage 1 - Proposal: this is worth working on.
- Stage 2 - Draft: initial spec.
- Stage 3 - Candidate: complete spec and initial browser implementations.
- Stage 4 - Finished: will be added to the next yearly release.
其中,preset-stage-3
用于支持 stage 3/4
,其余一一对应。另外需要注意,preset-stage-0~3
是一个包含关系,即preset-stage-0
包含preset-stage-1
所有的plugins和 stage 0 对应的plugins。
preset-env
详解preset-env
是 JS 中的 autoprefixer
,可以根据具体环境(浏览器/node版本)来应用不同的plugins,用于替代原来的babel-preset-es20xx/latest
(babel-preset-es2015/babel-preset-es2016/babel-preset-es2017
)。
严格来说,preset-env
支持的plugins超过babel-preset-latest(2015-2017)
,包括部分stage-3
支持的plugins及其它plugin——多出的plugins可以某种程度理解为preset-es2018
(不会出现了),并且随着落地标准越来越多(es2018/es2019/...),包括的plugins也会越来越多。
多出的plugins :
@babel/plugin-proposal-async-generator-functions
@babel/plugin-proposal-object-rest-spread
@babel/plugin-proposal-optional-catch-binding
@babel/plugin-proposal-unicode-property-regex
@babel/plugin-syntax-async-generators
@babel/plugin-syntax-object-rest-spread
@babel/plugin-syntax-optional-catch-binding
@babel/plugin-transform-dotall-regex
@babel/plugin-transform-new-target
下面来讲讲preset-env
的用法:
{
"presets": [
[
"env",
{
"targets": { // 目标环境
"browsers": [ // 浏览器
"last 2 versions",
"ie >= 10"
],
"node": "current" // node
},
"modules": true, // 是否转译module syntax,默认是 commonjs
"debug": true, // 是否输出启用的plugins列表
"spec": false, // 是否允许more spec compliant,但可能转译出的代码更慢
"loose": false, // 是否允许生成更简单es5的代码,但可能不那么完全符合ES6语义
"useBuiltIns": false, // 怎么运用 polyfill
"include": [], // 总是启用的 plugins
"exclude": [], // 强制不启用的 plugins
"forceAllTransforms": false, // 强制使用所有的plugins,用于只能支持ES5的uglify可以正确压缩代码
}
]
],
}
preset-env
的配置如上,大部分都很简单,重点讲一下useBuiltIns
。
useBuiltIns
用于指定怎么处理polyfill(通过@babel/polyfill
),可选的值为"usage" | "entry" | false
,默认是false
。
useBuiltIns: 'usage'
:当每个文件里用到(需要polyfill的特性)时,在文件中添加特定的import
语句。这可以保证每个polyfill的特性仅load一次。
/// input
var a = new Promise(); // a.js
var b = new Map(); // b.js
/// output
// a.js
import "core-js/modules/es6.promise";
var a = new Promise();
// b.js
import "core-js/modules/es6.map";
var b = new Map();
useBuiltIns: 'entry'
:替换import "@babel/polyfill" / require("@babel/polyfill")
语句为独立的(根据环境)需要引入的polyfill特性的import
语句。
// input
import "@babel/polyfill";
// output
import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
需要注意,在整个项目中,
"@babel/polyfill"
只能require一次,否则报错。建议用独立的entry文件引入。
useBuiltIns: false
,禁止使用上面两种转换,可以理解为不使用polyfill,此时需要使用者自己手动处理。
ReferenceError: regeneratorRuntime is not defined
错误:
需要注意,当你使用async/await
并被preset-env
转译后,运行时可能会出现以上错误,这是因为:
plugin-transform-regenerator
使用regenerator
来转译 async/generator 函数,但是它本身不包括regeneratorRuntime
,你需要使用babel-polyfill/regenerator runtime
来使regeneratorRuntime
存在。
通常情况下,加上transform-runtime
plugin即可。
@creeperyang babel7 这里这一段讲的应该是有问题的:
不适用polyfill
,只是没有按环境需要引入而已plugin-transform-regenerator 使用regenerator来转译 async/generator 函数,但是他本身不包含regeneratorRuntime。
是的, 但是babel-polyfill里面包含了regeneratorRuntim,只要使用了babel-polyfill,就可以支持这个generator。否则就要使用transform-runtime+babel-runtime来支持了
@cuiyongjian 赞同第一点,实际操作了一下,entry应该是按照目标浏览器的兼容性把所有需要的polyfill都放上去, 而usage就是上面提到的按照目标兼容性和按需原则引入,而当值为false的时候,就是不管三七二十一,把polyfill里面所有的内容都引入。 第二点的话,依我的理解一个完整和高兼容性的项目是需要babel-runtime和babel-polyfill一起支持的,babel-runtime提供runtimeHelper,babel-polyfill提供instance method。
包括拆分后的runtime-corejs2也不支持添加instance method。
@cuiyongjian @YardWill
其实按你们的说法,既然polyfill全引入了,怎么还会有 ReferenceError: regeneratorRuntime is not defined
的错误?
对于 useBuiltIns: false
,babel 将不会加入任何 polyfill。
可以打开debug
看到调试信息:
Using polyfills: No polyfills were added, since the
useBuiltInsoption was not set.
我自己的使用結果是,給您們做參考。
useBuiltIns: false
是會按照目前兼容性把需要的 polyfill
放在當前編譯的檔案
useBuiltIns: entry
是會把兼容性需要的 polyfill
放在唯一 import '@babel/polyfill'
的檔案裡面(我沒用過)
ReferenceError: regeneratorRuntime is not defined
不是 babel
的問題,是 regenerator-runtime
的問題,已經被修了,但還沒 publish https://github.com/facebook/regenerator/pull/353/files
.
如果有用 useBuiltIns
是可以不用在使用 babel-polyfill/regenerator
,useBuiltIns
加入 polyfill
的方式是 require('core-js/lib/<modules>')
,把需要 polyfill
的 function
,variable
以全域的方式補齊。 babel-polyfill/regenerator
則是以 const module = require('core-js/lib/<modules>')
的方式,僅當前編譯當案有 polyfill
。
比較起來 useBuiltIns: false
跟 babel-polyfill/regenerator
基本上是一樣的,只是一個是用全域的方式,一個是本地的方式。
const presets = [
[
'@babel/env',
{
targets: '> 0.25%, not dead',
useBuiltIns: false,
debug: true,
modules: 'commonjs',
},
],
];
我尝试了一下仅用这个preset,然后在index内加上import '@babel/polyfill';使用async await 并没有报ReferenceError: regeneratorRuntime is not defined 我也看过polyfill的代码,transform-regenerator库是被require了。 我感觉没什么问题,不知道你是怎么出现这种情况的。
@creeperyang 你也可以看一看最后打包出来的文件,看一下有没有这句代码。我按照上面的配置是能搜索到的。
__webpack_require__(/*! regenerator-runtime/runtime */ "./node_modules/regenerator-runtime/runtime.js");
@YardWill 理解你的意思了。你手动引入了@babel/polyfill
,再设置useBuiltIns: false
,这就是告诉preset-env
不要处理任何有关polyfill的事(你自己会手动处理,即你手动引入了@babel/polyfill
)。
所以我的意思是对的:设置useBuiltIns: false
时,babel不会帮你处理任何polyfill的事,你必须手动处理。
@creeperyang 多谢指教,不过我还有一个问题https://github.com/babel/babel/blob/master/packages/babel-preset-env/src/index.js#L286 为什么entry还需要自己引入polyfill? 以下是debug信息
Using polyfills with `entry` option:
`import '@babel/polyfill'` was not found.
Using polyfills with `entry` option:
Replaced `@babel/polyfill` with the following polyfills:
es6.array.copy-within { "android":"4.4", "chrome":"29", "ie":"11" }
es6.array.fill { "android":"4.4", "chrome":"29", "ie":"11" }
es6.array.find { "android":"4.4", "chrome":"29", "ie":"11" }// 太长就不贴全了,几乎所有polyfill和target有关。
@YardWill @HsuTing
以一个简单示例来说明。有文件 test.js
如下:
async function hello(a) {
console.log(a);
}
hello(Promise.resolve(1));
我们用不同的babel配置来验证一些东西。
1. 如果只设置useBuiltIns: false
:
可以看到,由于transform-async-to-generator
plugin起作用,async/wait
被翻译到了regeneratorRuntime
;
但是regeneratorRuntime
和Promise
都没有相应的polyfill被引入——即polyfill完全被忽略(不处理)。
"use strict";
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function hello(_x) {
return _hello.apply(this, arguments);
}
function _hello() {
_hello = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(a) {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
console.log(a);
case 1:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return _hello.apply(this, arguments);
}
hello(Promise.resolve(1));
2. 如果只设置useBuiltIns: 'usage'
:
可以看到文件开头引入了需要的promise/regeneratorRuntime
polyfill,但是由于我们未手动依赖(手动安装)regenerator-runtime
库,会报错 ReferenceError: regeneratorRuntime is not defined
。
同时(require("core-js/modules/es6.promise")
)同样会报错,因为我们也没有安装这个依赖。
"use strict";
require("regenerator-runtime/runtime"); // 污染全局,提供 regeneratorRuntime (代码`runtime = global.regeneratorRuntime = inModule ? module.exports : {};`)
require("core-js/modules/es6.promise"); // 污染全局,提供 Promise
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function hello(_x) {
return _hello.apply(this, arguments);
}
function _hello() {
_hello = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(a) {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
console.log(a);
case 1:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return _hello.apply(this, arguments);
}
hello(Promise.resolve(1));
3. 设置useBuiltIns: 'usage'
且同时使用plugin-transform-runtime
:
可以看到,上面的inline代码(如_asyncToGenerator等)被替换成@babel/runtime
中相应的引用了。
同时通过require("@babel/runtime/regenerator")
,@babel/runtime
为我们提供了缺失的regenerator-runtime
库。
但(require("core-js/modules/es6.promise")
)还是会报错,因为我们没有安装这个依赖。
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
// @babel/runtime/regenerator 依赖 regenerator-runtime/runtime,但以不污染全局的方式引入。
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
// 然后还是会引入regenerator-runtime/runtime;有重复引入和污染全局的问题;
// TODO:这里需要注意一下!问题待跟进
require("regenerator-runtime/runtime");
// 其实可以看到,core-js 我们并没有作为依赖,但这里却引入了。
// 这一块详见 <https://babeljs.io/docs/en/v7-migration#babel-runtime-babel-plugin-transform-runtime>
require("core-js/modules/es6.promise");
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
function hello(_x) {
return _hello.apply(this, arguments);
}
function _hello() {
_hello = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee(a) {
return _regenerator.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
console.log(a);
case 1:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return _hello.apply(this, arguments);
}
hello(Promise.resolve(1));
4. 设置useBuiltIns: 'usage'
且同时使用plugin-transform-runtime
(且配置core-js):
对比下上面,可以发现Promise
被正确修复——代码已经可以正常运行。
"use strict";
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
require("regenerator-runtime/runtime");
// promise 指向 @babel/runtime-corejs2/core-js/promise,被修复正确
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
function hello(_x) {
return _hello.apply(this, arguments);
}
function _hello() {
_hello = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee(a) {
return _regenerator.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
console.log(a);
case 1:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return _hello.apply(this, arguments);
}
hello(_promise.default.resolve(1));
@creeperyang 我想了解您說的未手動安裝是指 install
? 如果只是未手動安裝,不是只要在個別 install
就好了?我猜 @babel/env
本身因為還有處理其他東西,所以 babel
團隊不希望在把整個 @babel/polyfill
加入到 dependencies
裡面,才需要自行安裝,但不需要自己在 code
裡面一一引入所需要的 core-js
。
另外
regeneratorRuntime (代码
runtime = global.regeneratorRuntime = inModule ? module.exports : {};
)
這段我也有找到,但是我自己測試的情況是,在 只設置useBuiltIns: 'usage'
的情況下,就算裝了 core-js
或 @babel/polyfill
一樣會出現 ReferenceError: regeneratorRuntime is not defined
,但我手動把 require("regenerator-runtime/runtime");
改成 var regeneratorRuntime = require("regenerator-runtime/runtime");
是可以的,所以我猜他是沒有被加到全域變數裡面。
我有試過用 patch-package
方式把 https://github.com/facebook/regenerator/pull/353/files
這段 PR 覆蓋掉 node_modules
的 regenerator-runtime
,則確實是有把 regeneratorRuntime
加到全域變數,則不用另外在手動修正成 var regeneratorRuntime = require("regenerator-runtime/runtime");
。
@HsuTing
https://github.com/facebook/regenerator/pull/353/files 里已经不在注册全局的regeneratorRuntime
了,但是@babel/runtime@7.0.0
或者说regenerator-runtime <= 0.13.0
里的regenerator-runtime/runtime
都是会直接提供全局的regeneratorRuntime
的(挂载到global上)。
我说的 手動安裝 更多的意思是必须自己指定 @babel/polyfill
或者 @babel/runtime
等包作为依赖并 install,而不是 babel 自动添加/管理。
现在对generator这里更明白一点了:
写了一篇长文,啰嗦了这些实验过程..
useBuiltIns
有项目地址吗
了解
Babel 6
生态现在写一个babel的简介好像已经不太必要了(太晚了😄 )。但大多数情况下,会配置
babel
来编译代码,不代表我们清楚babel
的概念,而且Babel 6
相关的多个babel-xx
包还是容易让人混淆的。所以这里还是希望帮助理清整个Babel 6
生态。参考:
Babel 6
的核心特性(相比5的巨大变化)我刚开始用
babel
的时候,版本是5,一个月后Babel 6
发布——变化简直天翻地覆。相比前一版本,
Babel 6
最大的变化是更模块化,各种内置库都被分散到独立的模块;其次,让所有插件可选,这意味着Babel默认不会编译ES2015代码,并且所有的transformer完全独立;同时,为了减少配置的复杂性,引入了preset;最后,提升了性能。下面列出一些
Babel 6
的核心模块/变化:babel
package被弃用。我们可以看babel@6.x的源码,两个提示很明显:
babel-core
。babel-cli
。babel-core
是babel的core compiler,主要用来对你的源码跑一系列变换(transform)。但默认情况下,不会应用任何变换——你必须自己安装和注册这些变换。babel-cli
是babel的command line,有babel
/babel-external-helpers
/babel-node
3个命令。babel-doctor
已被移除,见https://github.com/babel/babel/issues/4678。babel
即用于编译代码。babel-external-helpers
用于生成一段js代码(里面是一些helper函数)。这些helper如果被用到,一般被置于生成代码顶部(公用),所以生成的代码不会有内连这些helper好几遍。但是如果你有多个文件的话,你可能又要重复这些helper好几遍了。所以你可以生成这样一份代码,然后在每个文件中直接引入(node通过require
,browser通过<script>
)。详情见external-helpers。babel-node
是方便开发的node二进制(非生产使用),内置了babel-polyfill
,并用babel-register
来编译被require的模块。babel-register
,require hook
,替换了node的require
。node_modules
内的模块,则使用node的require
。require
,自动编译模块。Babel 6
的plugins
详情见https://babeljs.io/docs/plugins/。
这里不多说,只简单说两点:
plugins
。babel-preset-es2015
包括了完整的ES2015
特性,引入它即可编译ES2015
代码到ES5
。用transform还是polyfill实现?
babel-core
仅仅聚焦于code transform,所以不是什么事都可以用babel
来转换的。比如,检索上面的plugins列表,你会发现没有一个plugin用来转换
Promise
;事实上,如果环境不支持Promise
,你应该自己引入相应polyfill。那么什么时候应该用tranform,什么时候该用polyfill呢?如果一个新特性你可以用
ES5
实现,那么,你应该用polyfill,比如Array.from
。否则,你应该用transform,比如箭头函数。babel-polyfill
vsbabel-runtime
这可能是babel中最让人误解的一组概念:当你需要支持
ES2015
的所有特性时,究竟用babel-polyfill
还是babel-runtime
?babel-polyfill
和babel-runtime
是达成同一种功能(模拟ES2015
环境,包括global keywords
,prototype methods
,都基于core-js
提供的一组polyfill和一个generator runtime
)的两种方式:babel-polyfill
通过向全局对象和内置对象的prototype上添加方法来达成目的。这意味着你一旦引入babel-polyfill
,像Map
,Array.prototype.find
这些就已经存在了——全局空间被污染。babel-runtime
不会污染全局空间和内置对象原型。事实上babel-runtime
是一个模块,你可以把它作为依赖来达成ES2015
的支持。比如当前环境不支持
Promise
,你可以通过require(‘babel-runtime/core-js/promise’)
来获取Promise
。这很有用但不方便。幸运的是,babel-runtime
并不是设计来直接使用的——它是和babel-plugin-transform-runtime
一起使用的。babel-plugin-transform-runtime
会自动重写你使用Promise
的代码,转换为使用babel-runtime
导出(export)的Promise-like
对象。注意: 所以
plugin-transform-runtime
一般用于开发(devDependencies),而runtime
自身用于部署的代码(dependencies),两者配合来一起工作。那么我们什么时候用
babel-polyfill
,什么时候用babel-runtime
?babel-polyfill
会污染全局空间,并可能导致不同版本间的冲突,而babel-runtime
不会。从这点看应该用babel-runtime
。babel-runtime
有个缺点,它不模拟实例方法,即内置对象原型上的方法,所以类似Array.prototype.find
,你通过babel-runtime
是无法使用的。require('babel-polyfill')
),这会导致代码量很大。请按需引用最好。