@babel/plugin-transform-runtime
A plugin that enables the re-use of Babel's injected helper code to save on codesize.
Instance methods such as
"foobar".includes("foo")
will only work with
core-js@3
. If you need to polyfill them, you can directly import
"core-js"
or use
@babel/preset-env
's
useBuiltIns
option.
Installation
Install it as development dependency.
- npm
- Yarn
- pnpm
npm install --save-dev @babel/plugin-transform-runtime
yarn add --dev @babel/plugin-transform-runtime
pnpm add --save-dev @babel/plugin-transform-runtime
and
@babel/runtime
as a production dependency (since it's for the "runtime").
- npm
- Yarn
- pnpm
npm install --save @babel/runtime
yarn add @babel/runtime
pnpm add @babel/runtime
The transformation plugin is typically used only in development, but the runtime itself will be depended on by your deployed code. See the examples below for more details.
When this plugin is enabled, the
useBuiltIns
option in
@babel/preset-env
must not be set. Otherwise, this plugin may not able to completely sandbox the environment.
Why?
Babel uses very small helpers for common functions such as
_extend
. By default this will be added to every file that requires it. This duplication is sometimes unnecessary, especially when your application is spread out over multiple files.
This is where the
@babel/plugin-transform-runtime
plugin comes in: all of the helpers will reference the module
@babel/runtime
to avoid duplication across your compiled output. The runtime will be compiled into your build.
Another purpose of this transformer is to create a sandboxed environment for your code. If you directly import
core-js
or
@babel/polyfill
and the built-ins it provides such as
Promise
,
Set
and
Map
, those will pollute the global scope. While this might be ok for an app or a command line tool, it becomes a problem if your code is a library which you intend to publish for others to use or if you can't exactly control the environment in which your code will run.
The transformer will alias these built-ins to
core-js
so you can use them seamlessly without having to require the polyfill.
See the technical details section for more information on how this works and the types of transformations that occur.
Usage
With a configuration file (Recommended)
Without options:
{
"plugins": ["@babel/plugin-transform-runtime"]
}
With options (and their defaults):
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": false,
"helpers": true,
"regenerator": true,
"version": "7.0.0-beta.0"
}
]
]
}
The plugin defaults to assuming that all polyfillable APIs will be provided by the user. Otherwise the
corejs
option needs to be specified.
Via CLI
babel --plugins @babel/plugin-transform-runtime script.js
Via Node API
require("@babel/core").transformSync("code", {
plugins: ["@babel/plugin-transform-runtime"],
});
Options
absoluteRuntime
boolean
or
string
, defaults to
false
.
This allows users to run
transform-runtime
broadly across a whole project. By default,
transform-runtime
imports from
@babel/runtime/foo
directly, but that only works if
@babel/runtime
is in the
node_modules
of the file that is being compiled. This can be problematic for nested
node_modules
, npm-linked modules, or CLIs that reside outside the user's project, among other cases. To avoid worrying about how the runtime module's location is resolved, this allows users to resolve the runtime once up front, and then insert absolute paths to the runtime into the output code.
Using absolute paths is not desirable if files are compiled for use at a later time, but in contexts where a file is compiled and then immediately consumed, they can be quite helpful.
You can read more about configuring plugin options here
corejs
false
,
2
,
3
or
{ version: 2 | 3, proposals: boolean }
, defaults to
false
.
e.g.
['@babel/plugin-transform-runtime', { corejs: 3 }],
History
Version | Changes |
---|---|
v7.4.0
|
Supports
{ proposals: boolean }
|
Specifying a number will rewrite the helpers that need polyfillable APIs to reference helpers from that (major) version of
core-js
instead
Please note that
corejs: 2
only supports global variables (e.g.
Promise
) and static properties (e.g.
Array.from
), while
corejs: 3
also supports instance properties (e.g.
[].includes
).
By default,
@babel/plugin-transform-runtime
doesn't polyfill proposals. If you are using
corejs: 3
, you can opt into this by enabling using the
proposals: true
option.
This option requires changing the dependency used to provide the necessary runtime helpers:
corejs
option
|
Install command |
---|---|
false
|
npm install --save @babel/runtime
|
2
|
npm install --save @babel/runtime-corejs2
|
3
|
npm install --save @babel/runtime-corejs3
|
The
corejs
option will be removed in Babel 8. To inject polyfills, you can use
babel-plugin-polyfill-corejs3
or
babel-plugin-polyfill-corejs2
directly.
helpers
boolean
, defaults to
true
.
Toggles whether or not inlined Babel helpers (
classCallCheck
,
extends
, etc.) are replaced with calls to
@babel/runtime
(or equivalent package).
For more information, see Helper aliasing .
The
helpers
option will be removed in Babel 8, as this plugin will only be used to inject helpers (including
regeneratorRuntime
, which will be handled as any other Babel helper).
moduleName
History
Version | Changes |
---|---|
v7.24.0
|
Added
moduleName
option
|
string
, defaults to
@babel/runtime
.
This option controls which package of helpers
@babel/plugin-transform-runtime
will use when injecting imports. It uses the following priority:
moduleName
option, if specified
babel-plugin-polyfill-*
plugin
babel-plugin-polyfill-corejs3
suggests
@babel/runtime-corejs3
babel-plugin-polyfill-corejs2
suggests
@babel/runtime-corejs2
@babel/runtime
Note that specifying the
corejs
option will internally enable the corresponding
babel-plugin-polyfill-corejs*
plugin, thus it has an effect on the final module name.
regenerator
boolean
, defaults to
true
.
In older Babel version, this option used to toggles whether or not generator functions were transformed to use a regenerator runtime that does not pollute the global scope.
For more information, see Regenerator aliasing .
The
regenerator
option will be removed in Babel 8, as it will not be necessary anymore.
useESModules
boolean
, defaults to
false
.
History
Version | Changes |
---|---|
v7.13.0
|
This option has been deprecated |
When enabled, the transform will use helpers that do not get run through
@babel/plugin-transform-modules-commonjs
. This allows for smaller builds in module
systems like webpack, since it doesn't need to preserve commonjs semantics.
For example, here is the
classCallCheck
helper with
useESModules
disabled:
exports.__esModule = true;
exports.default = function(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
And, with it enabled:
export default function(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
The
useESModules
option has been deprecated and will be removed in Babel 8: starting from version
7.13.0
,
@babel/runtime
's
package.json
uses
"exports"
option to automatically choose between CJS and ESM helpers.
version
By default transform-runtime assumes that
@babel/[email protected]
is installed. If you have later versions of
@babel/runtime
(or their corejs counterparts e.g.
@babel/runtime-corejs3
) installed or listed as a dependency, transform-runtime can use more advanced features.
For example if you depend on
@babel/runtime@^7.24.0
you can transpile your code with
{
"plugins": [
["@babel/plugin-transform-runtime", {
"version": "^7.24.0"
}]
]
}
which results in a smaller bundle size.
Technical details
The
transform-runtime
transformer plugin does three things:
@babel/runtime/regenerator
when you use generators/async functions (toggleable with the
regenerator
option).
core-js
for helpers if necessary instead of assuming it will be polyfilled by the user (toggleable with the
corejs
option)
@babel/runtime/helpers
instead (toggleable with the
helpers
option).
What does this actually mean though? Basically, you can use built-ins such as
Promise
,
Set
,
Symbol
, etc., as well use all the Babel features that require a polyfill seamlessly, without global pollution, making it extremely suitable for libraries.
Make sure you include
@babel/runtime
as a dependency.
Regenerator aliasing
Whenever you use a generator function or async function:
function* foo() {}
the following is generated:
"use strict";
var _marked = [foo].map(regeneratorRuntime.mark);
function foo() {
return regeneratorRuntime.wrap(
function foo$(_context) {
while (1) {
switch ((_context.prev = _context.next)) {
case 0:
case "end":
return _context.stop();
}
}
},
_marked[0],
this
);
}
This isn't ideal since it relies on the regenerator runtime being included, which pollutes the global scope.
With the
runtime
transformer, however, it is compiled to:
"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
);
}
This means that you can use the regenerator runtime without polluting your current environment.
core-js
aliasing
Sometimes you may want to use new built-ins such as
Map
,
Set
,
Promise
etc. Your only way
to use these is usually to include a globally polluting polyfill.
This is with the
corejs
option.
The plugin transforms the following:
var sym = Symbol();
var promise = Promise.resolve();
var check = arr.includes("yeah!");
console.log(arr[Symbol.iterator]());
into the following:
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));
This means is that you can seamlessly use these native built-ins and methods without worrying about where they come from.
NOTE:
Instance methods such as
"foobar".includes("foo")
will only work when using
corejs: 3
.
Helper aliasing
Usually Babel will place helpers at the top of your file to do common tasks to avoid
duplicating the code around in the current file. Sometimes these helpers can get a
little bulky and add unnecessary duplication across files. The
runtime
transformer replaces all the helper calls to a module.
That means that the following code:
class Person {}
usually turns into:
"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);
};
the
runtime
transformer however turns this into:
"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);
};
Removed options
The following options were removed in Babel 7.0.0: