babel中的runtime-corejs和plugin-transform-runtime


本文作者: jsweibo

本文链接: https://jsweibo.github.io/2019/08/10/babel%E4%B8%AD%E7%9A%84runtime-corejs%E5%92%8Cplugin-transform-runtime/

摘要

本文主要讲述了:

  1. 背景
  2. 安装
  3. 示例
  4. 总结

正文

背景

如果你不了解什么是@babel/runtime@babel/plugin-transform-runtime,请先阅读babel中的runtime和plugin-transform-runtime

如果直接使用core-jsregenerator-runtime作为 polyfill,会污染全局作用域。

对于普通的项目来说,也许还可以接受。但对于一个第三方库,那么必然面临一个问题:库的使用者未必愿意接受全局作用域污染,这可能会和库的使用者本身的代码存在冲突(其 polyfill 可能不是通过core-jsregenerator-runtime实现的)。

@babel/plugin-transform-runtime通过引入@babel/runtime-corejs解决了这个问题。

@babel/runtime其实就是把辅助函数、regenerator-runtime封装在了一起。

@babel/runtime-corejs其实就是把辅助函数、core-jsregenerator-runtime封装在了一起。

因此@babel/runtime-corejs不仅能替代@babel/runtime,而且还能提供core-js

只需要安装@babel/runtime-corejs,然后开启@babel/plugin-transform-runtimecorejs属性(默认关闭)和regenerator属性(默认开启),此时@babel/plugin-transform-runtime会做两件事:

  • 将每个编译后的文件中定义的辅助函数转换为对@babel/runtime的引用
  • 将每个编译后的文件中的全局作用域的 polyfill 转换为局部作用域的 polyfill,尽量避免污染全局作用域

注意:@babel/runtime-corejs分为 2 个版本:

  • @babel/runtime-corejs2
  • @babel/runtime-corejs3

我们将通过下面的示例来解释两者的区别。

安装

1
2
3
4
5
#!/usr/bin/env bash

npm install --save-dev @babel/core @babel/cli @babel/preset-env
npm install --save-dev @babel/plugin-transform-runtime
npm install @babel/runtime @babel/runtime-corejs2 @babel/runtime-corejs3

示例

示例 1

learn_babel/babel.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
ie: 11,
},
useBuiltIns: 'usage',
corejs: 2,
},
],
],
plugins: ['@babel/plugin-transform-runtime'],
};

源文件:

learn_babel/index.js

1
2
3
4
5
class Foobar {}
new Promise((resolve, reject) => {});
console.log(Array.isArray);
console.log('foobar'.includes);
console.log('foobar'.match);

输出:

learn_babel/index.compiled.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
'use strict';

var _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault');

require('core-js/modules/es6.object.to-string.js');

require('core-js/modules/es6.promise.js');

require('core-js/modules/es6.string.includes.js');

var _createClass2 = _interopRequireDefault(
require('@babel/runtime/helpers/createClass')
);

var _classCallCheck2 = _interopRequireDefault(
require('@babel/runtime/helpers/classCallCheck')
);

var Foobar = /*#__PURE__*/ (0, _createClass2.default)(function Foobar() {
(0, _classCallCheck2.default)(this, Foobar);
});
new Promise(function (resolve, reject) {});
console.log(Array.isArray);
console.log('foobar'.includes);
console.log('foobar'.match);

示例 2

learn_babel/babel.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
ie: 11,
},
useBuiltIns: 'usage',
corejs: 2,
},
],
],
plugins: [
[
'@babel/plugin-transform-runtime',
{
corejs: 2,
},
],
],
};

源文件:

learn_babel/index.js

1
2
3
4
5
class Foobar {}
new Promise((resolve, reject) => {});
console.log(Array.isArray);
console.log('foobar'.includes);
console.log('foobar'.match);

输出:

learn_babel/index.compiled.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
'use strict';

var _interopRequireDefault = require('@babel/runtime-corejs2/helpers/interopRequireDefault');

require('core-js/modules/es6.string.includes.js');

var _promise = _interopRequireDefault(
require('@babel/runtime-corejs2/core-js/promise')
);

var _isArray = _interopRequireDefault(
require('@babel/runtime-corejs2/core-js/array/is-array')
);

var _createClass2 = _interopRequireDefault(
require('@babel/runtime-corejs2/helpers/createClass')
);

var _classCallCheck2 = _interopRequireDefault(
require('@babel/runtime-corejs2/helpers/classCallCheck')
);

var Foobar = /*#__PURE__*/ (0, _createClass2.default)(function Foobar() {
(0, _classCallCheck2.default)(this, Foobar);
});
new _promise.default(function (resolve, reject) {});
console.log(_isArray.default);
console.log('foobar'.includes);
console.log('foobar'.match);

示例 3

learn_babel/babel.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
ie: 11,
},
useBuiltIns: 'usage',
corejs: 3,
},
],
],
plugins: ['@babel/plugin-transform-runtime'],
};

源文件:

learn_babel/index.js

1
2
3
4
5
class Foobar {}
new Promise((resolve, reject) => {});
console.log(Array.isArray);
console.log('foobar'.includes);
console.log('foobar'.match);

输出:

learn_babel/index.compiled.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
'use strict';

var _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault');

require('core-js/modules/es.object.to-string.js');

require('core-js/modules/es.promise.js');

require('core-js/modules/es.string.includes.js');

require('core-js/modules/es.regexp.exec.js');

require('core-js/modules/es.string.match.js');

var _createClass2 = _interopRequireDefault(
require('@babel/runtime/helpers/createClass')
);

var _classCallCheck2 = _interopRequireDefault(
require('@babel/runtime/helpers/classCallCheck')
);

var Foobar = /*#__PURE__*/ (0, _createClass2.default)(function Foobar() {
(0, _classCallCheck2.default)(this, Foobar);
});
new Promise(function (resolve, reject) {});
console.log(Array.isArray);
console.log('foobar'.includes);
console.log('foobar'.match);

示例 4

learn_babel/babel.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
ie: 11,
},
useBuiltIns: 'usage',
corejs: 3,
},
],
],
plugins: [
[
'@babel/plugin-transform-runtime',
{
corejs: 3,
},
],
],
};

源文件:

learn_babel/index.js

1
2
3
4
5
class Foobar {}
new Promise((resolve, reject) => {});
console.log(Array.isArray);
console.log('foobar'.includes);
console.log('foobar'.match);

输出:

learn_babel/index.compiled.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
'use strict';

var _interopRequireDefault = require('@babel/runtime-corejs3/helpers/interopRequireDefault');

require('core-js/modules/es.regexp.exec.js');

require('core-js/modules/es.string.match.js');

var _promise = _interopRequireDefault(
require('@babel/runtime-corejs3/core-js-stable/promise')
);

var _isArray = _interopRequireDefault(
require('@babel/runtime-corejs3/core-js-stable/array/is-array')
);

var _includes = _interopRequireDefault(
require('@babel/runtime-corejs3/core-js-stable/instance/includes')
);

var _createClass2 = _interopRequireDefault(
require('@babel/runtime-corejs3/helpers/createClass')
);

var _classCallCheck2 = _interopRequireDefault(
require('@babel/runtime-corejs3/helpers/classCallCheck')
);

var Foobar = /*#__PURE__*/ (0, _createClass2.default)(function Foobar() {
(0, _classCallCheck2.default)(this, Foobar);
});
new _promise.default(function (resolve, reject) {});
console.log(_isArray.default);
console.log((0, _includes.default)('foobar'));
console.log('foobar'.match);

总结

对比示例 1 和示例 2、示例 3 和示例 4,可以得到结论:

  • @babel/runtime-corejs + @babel/plugin-transform-runtime也无法完全避免污染全局作用域
  • 除非手动开启@babel/plugin-transform-runtimecorejs属性,否则@babel/plugin-transform-runtime默认不会将core-js的引用替换为@babel/runtime-corejs

对比示例 2 和示例 4,可以得到结论:

  • @babel/runtime-corejs2为静态方法提供了不会污染全局作用域的 polyfill,但并没有为原型方法提供任何 polyfill
  • @babel/runtime-corejs3在前代的基础上,为部分原型方法提供了不会污染全局作用域的 polyfill

参考资料

本文作者: jsweibo

本文链接: https://jsweibo.github.io/2019/08/10/babel%E4%B8%AD%E7%9A%84runtime-corejs%E5%92%8Cplugin-transform-runtime/


本文对你有帮助?请支持我


支付宝
微信