UNPKG

9.89 kBMarkdownView Raw
1# @babel/plugin-transform-runtime
2
3> Externalise references to helpers and built-ins, automatically polyfilling your code without polluting globals. (This plugin is recommended in a library/tool)
4
5NOTE: Instance methods such as `"foobar".includes("foo")` will not work since that would require modification of existing built-ins (Use [`@babel/polyfill`](http://babeljs.io/docs/usage/polyfill) for that).
6
7## Why?
8
9Babel 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.
10
11This 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.
12
13Another purpose of this transformer is to create a sandboxed environment for your code. If you use [@babel/polyfill](http://babeljs.io/docs/usage/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.
14
15The transformer will alias these built-ins to `core-js` so you can use them seamlessly without having to require the polyfill.
16
17See the [technical details](#technical-details) section for more information on how this works and the types of transformations that occur.
18
19## Installation
20
21**NOTE - Production vs. development dependencies**
22
23In most cases, you should install `@babel/plugin-transform-runtime` as a development dependency (with `--save-dev`).
24
25```sh
26npm install --save-dev @babel/plugin-transform-runtime
27```
28
29and `@babel/runtime` as a production dependency (with `--save`).
30
31```sh
32npm install --save @babel/runtime
33```
34
35The transformation plugin is typically used only in development, but the runtime itself will be depended on by your deployed/published code. See the examples below for more details.
36
37## Usage
38
39### Via `.babelrc` (Recommended)
40
41Add the following line to your `.babelrc` file:
42
43Without options:
44
45```json
46{
47 "plugins": ["@babel/plugin-transform-runtime"]
48}
49```
50
51With options:
52
53```json
54{
55 "plugins": [
56 ["@babel/plugin-transform-runtime", {
57 "helpers": false,
58 "polyfill": false,
59 "regenerator": true,
60 "moduleName": "@babel/runtime"
61 }]
62 ]
63}
64```
65
66### Via CLI
67
68```sh
69babel --plugins @babel/plugin-transform-runtime script.js
70```
71
72### Via Node API
73
74```javascript
75require("@babel/core").transform("code", {
76 plugins: ["@babel/plugin-transform-runtime"]
77});
78```
79
80## Options
81
82### `helpers`
83
84`boolean`, defaults to `true`.
85
86Toggles whether or not inlined Babel helpers (`classCallCheck`, `extends`, etc.) are replaced with calls to `moduleName`.
87
88For more information, see [Helper aliasing](#helper-aliasing).
89
90### `polyfill`
91
92`boolean`, defaults to `true`.
93
94Toggles whether or not new built-ins (`Promise`, `Set`, `Map`, etc.) are transformed to use a non-global polluting polyfill.
95
96For more information, see [`core-js` aliasing](#core-js-aliasing).
97
98### `regenerator`
99
100`boolean`, defaults to `true`.
101
102Toggles whether or not generator functions are transformed to use a regenerator runtime that does not pollute the global scope.
103
104For more information, see [Regenerator aliasing](#regenerator-aliasing).
105
106### `moduleName`
107
108`string`, defaults to `"@babel/runtime"`.
109
110Sets the name/path of the module used when importing helpers.
111
112Example:
113
114```json
115{
116 "moduleName": "flavortown/runtime"
117}
118```
119
120```js
121import extends from 'flavortown/runtime/helpers/extends';
122```
123
124### `useBuiltIns`
125
126`boolean`, defaults to `false`.
127
128When enabled, the transform will use helpers that do not use _any_ polyfills
129from `core-js`.
130
131For example, here is the `instance` helper with `useBuiltIns` disabled:
132
133```js
134exports.__esModule = true;
135
136var _hasInstance = require("../core-js/symbol/has-instance");
137
138var _hasInstance2 = _interopRequireDefault(_hasInstance);
139
140var _symbol = require("../core-js/symbol");
141
142var _symbol2 = _interopRequireDefault(_symbol);
143
144exports.default = function (left, right) {
145 if (right != null && typeof _symbol2.default !== "undefined" && right[_hasInstance2.default]) {
146 return right[_hasInstance2.default](left);
147 } else {
148 return left instanceof right;
149 }
150};
151
152function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
153```
154
155And, with it enabled:
156
157```js
158exports.__esModule = true;
159
160exports.default = function (left, right) {
161 if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
162 return right[Symbol.hasInstance](left);
163 } else {
164 return left instanceof right;
165 }
166};
167```
168
169### `useESModules`
170
171`boolean`, defaults to `false`.
172
173When enabled, the transform will use helpers that do not get run through
174`@babel/plugin-transform-modules-commonjs`. This allows for smaller builds in module
175systems like webpack, since it doesn't need to preserve commonjs semantics.
176
177For example, here is the `classCallCheck` helper with `useESModules` disabled:
178
179```js
180exports.__esModule = true;
181
182exports.default = function (instance, Constructor) {
183 if (!(instance instanceof Constructor)) {
184 throw new TypeError("Cannot call a class as a function");
185 }
186};
187```
188
189And, with it enabled:
190
191```js
192export default function (instance, Constructor) {
193 if (!(instance instanceof Constructor)) {
194 throw new TypeError("Cannot call a class as a function");
195 }
196}
197```
198
199## Technical details
200
201The `runtime` transformer plugin does three things:
202
203* Automatically requires `@babel/runtime/regenerator` when you use generators/async functions.
204* Automatically requires `@babel/runtime/core-js` and maps ES6 static methods and built-ins.
205* Removes the inline Babel helpers and uses the module `@babel/runtime/helpers` instead.
206
207What 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.
208
209Make sure you include `@babel/runtime` as a dependency.
210
211### Regenerator aliasing
212
213Whenever you use a generator function or async function:
214
215```javascript
216function* foo() {
217
218}
219```
220
221the following is generated:
222
223```javascript
224"use strict";
225
226var _marked = [foo].map(regeneratorRuntime.mark);
227
228function foo() {
229 return regeneratorRuntime.wrap(function foo$(_context) {
230 while (1) {
231 switch (_context.prev = _context.next) {
232 case 0:
233 case "end":
234 return _context.stop();
235 }
236 }
237 }, _marked[0], this);
238}
239```
240
241This isn't ideal since it relies on the regenerator runtime being included, which
242pollutes the global scope.
243
244With the `runtime` transformer, however, it is compiled to:
245
246```javascript
247"use strict";
248
249var _regenerator = require("@babel/runtime/regenerator");
250
251var _regenerator2 = _interopRequireDefault(_regenerator);
252
253function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
254
255var _marked = [foo].map(_regenerator2.default.mark);
256
257function foo() {
258 return _regenerator2.default.wrap(function foo$(_context) {
259 while (1) {
260 switch (_context.prev = _context.next) {
261 case 0:
262 case "end":
263 return _context.stop();
264 }
265 }
266 }, _marked[0], this);
267}
268```
269
270This means that you can use the regenerator runtime without polluting your current environment.
271
272### `core-js` aliasing
273
274Sometimes you may want to use new built-ins such as `Map`, `Set`, `Promise` etc. Your only way
275to use these is usually to include a globally polluting polyfill.
276
277What the `runtime` transformer does is transform the following:
278
279```javascript
280var sym = Symbol();
281
282var promise = new Promise;
283
284console.log(arr[Symbol.iterator]());
285```
286
287into the following:
288
289```javascript
290"use strict";
291
292var _getIterator2 = require("@babel/runtime/core-js/get-iterator");
293
294var _getIterator3 = _interopRequireDefault(_getIterator2);
295
296var _promise = require("@babel/runtime/core-js/promise");
297
298var _promise2 = _interopRequireDefault(_promise);
299
300var _symbol = require("@babel/runtime/core-js/symbol");
301
302var _symbol2 = _interopRequireDefault(_symbol);
303
304function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
305
306var sym = (0, _symbol2.default)();
307
308var promise = new _promise2.default();
309
310console.log((0, _getIterator3.default)(arr));
311```
312
313This means is that you can seamlessly use these native built-ins and static methods
314without worrying about where they come from.
315
316**NOTE:** Instance methods such as `"foobar".includes("foo")` will **not** work.
317
318### Helper aliasing
319
320Usually Babel will place helpers at the top of your file to do common tasks to avoid
321duplicating the code around in the current file. Sometimes these helpers can get a
322little bulky and add unnecessary duplication across files. The `runtime`
323transformer replaces all the helper calls to a module.
324
325That means that the following code:
326
327```javascript
328class Person {
329}
330```
331
332usually turns into:
333
334```javascript
335"use strict";
336
337function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
338
339var Person = function Person() {
340 _classCallCheck(this, Person);
341};
342```
343
344the `runtime` transformer however turns this into:
345
346```javascript
347"use strict";
348
349var _classCallCheck2 = require("@babel/runtime/helpers/classCallCheck");
350
351var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
352
353function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
354
355var Person = function Person() {
356 (0, _classCallCheck3.default)(this, Person);
357};
358```