1 | # babel-plugin-transform-runtime
|
2 |
|
3 | > Externalise references to helpers and builtins, automatically polyfilling your code without polluting globals. (This plugin is recommended in a library/tool)
|
4 |
|
5 | NOTE: Instance methods such as `"foobar".includes("foo")` will not work since that would require modification of existing builtins (Use [`babel-polyfill`](http://babeljs.io/docs/usage/polyfill) for that).
|
6 |
|
7 | ## Why?
|
8 |
|
9 | 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.
|
10 |
|
11 | This is where the `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 |
|
13 | Another 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 |
|
15 | The transformer will alias these built-ins to `core-js` so you can use them seamlessly without having to require the polyfill.
|
16 |
|
17 | See 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 |
|
23 | In most cases, you should install `babel-plugin-transform-runtime` as a development dependency (with `--save-dev`).
|
24 |
|
25 | ```sh
|
26 | npm install --save-dev babel-plugin-transform-runtime
|
27 | ```
|
28 |
|
29 | and `babel-runtime` as a production dependency (with `--save`).
|
30 |
|
31 | ```sh
|
32 | npm install --save babel-runtime
|
33 | ```
|
34 |
|
35 | The 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 |
|
41 | Add the following line to your `.babelrc` file:
|
42 |
|
43 | ```js
|
44 | // without options
|
45 | {
|
46 | "plugins": ["transform-runtime"]
|
47 | }
|
48 |
|
49 | // with options
|
50 | {
|
51 | "plugins": [
|
52 | ["transform-runtime", {
|
53 | "helpers": false, // defaults to true
|
54 | "polyfill": false, // defaults to true
|
55 | "regenerator": true, // defaults to true
|
56 | "moduleName": "babel-runtime" // defaults to "babel-runtime"
|
57 | }]
|
58 | ]
|
59 | }
|
60 | ```
|
61 |
|
62 | ### Via CLI
|
63 |
|
64 | ```sh
|
65 | babel --plugins transform-runtime script.js
|
66 | ```
|
67 |
|
68 | ### Via Node API
|
69 |
|
70 | ```javascript
|
71 | require("babel-core").transform("code", {
|
72 | plugins: ["transform-runtime"]
|
73 | });
|
74 | ```
|
75 |
|
76 | ## Technical details
|
77 |
|
78 | The `runtime` transformer plugin does three things:
|
79 |
|
80 | * Automatically requires `babel-runtime/regenerator` when you use generators/async functions.
|
81 | * Automatically requires `babel-runtime/core-js` and maps ES6 static methods and built-ins.
|
82 | * Removes the inline babel helpers and uses the module `babel-runtime/helpers` instead.
|
83 |
|
84 | 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.
|
85 |
|
86 | Make sure you include `babel-runtime` as a dependency.
|
87 |
|
88 | ### Regenerator aliasing
|
89 |
|
90 | Whenever you use a generator function or async function:
|
91 |
|
92 | ```javascript
|
93 | function* foo() {
|
94 |
|
95 | }
|
96 | ```
|
97 |
|
98 | the following is generated:
|
99 |
|
100 | ```javascript
|
101 | "use strict";
|
102 |
|
103 | var _marked = [foo].map(regeneratorRuntime.mark);
|
104 |
|
105 | function foo() {
|
106 | return regeneratorRuntime.wrap(function foo$(_context) {
|
107 | while (1) switch (_context.prev = _context.next) {
|
108 | case 0:
|
109 | case "end":
|
110 | return _context.stop();
|
111 | }
|
112 | }, _marked[0], this);
|
113 | }
|
114 | ```
|
115 |
|
116 | This isn't ideal as then you have to include the regenerator runtime which
|
117 | pollutes the global scope.
|
118 |
|
119 | Instead what the `runtime` transformer does it compile that to:
|
120 |
|
121 | ```javascript
|
122 | "use strict";
|
123 |
|
124 | var _regenerator = require("babel-runtime/regenerator");
|
125 |
|
126 | var _regenerator2 = _interopRequireDefault(_regenerator);
|
127 |
|
128 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
129 |
|
130 | var _marked = [foo].map(_regenerator2.default.mark);
|
131 |
|
132 | function foo() {
|
133 | return regeneratorRuntime.wrap(function foo$(_context) {
|
134 | while (1) switch (_context.prev = _context.next) {
|
135 | case 0:
|
136 | case "end":
|
137 | return _context.stop();
|
138 | }
|
139 | }, _marked[0], this);
|
140 | }
|
141 | ```
|
142 |
|
143 | This means that you can use the regenerator runtime without polluting your current environment.
|
144 |
|
145 | ### `core-js` aliasing
|
146 |
|
147 | Sometimes you may want to use new built-ins such as `Map`, `Set`, `Promise` etc. Your only way
|
148 | to use these is usually to include a globally polluting polyfill.
|
149 |
|
150 | What the `runtime` transformer does is transform the following:
|
151 |
|
152 | ```javascript
|
153 | var sym = Symbol();
|
154 |
|
155 | var promise = new Promise;
|
156 |
|
157 | console.log(arr[Symbol.iterator]());
|
158 | ```
|
159 |
|
160 | into the following:
|
161 |
|
162 | ```javascript
|
163 | "use strict";
|
164 |
|
165 | var _getIterator2 = require("babel-runtime/core-js/get-iterator");
|
166 |
|
167 | var _getIterator3 = _interopRequireDefault(_getIterator2);
|
168 |
|
169 | var _promise = require("babel-runtime/core-js/promise");
|
170 |
|
171 | var _promise2 = _interopRequireDefault(_promise);
|
172 |
|
173 | var _symbol = require("babel-runtime/core-js/symbol");
|
174 |
|
175 | var _symbol2 = _interopRequireDefault(_symbol);
|
176 |
|
177 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
178 |
|
179 | var sym = (0, _symbol2.default)();
|
180 |
|
181 | var promise = new _promise2.default();
|
182 |
|
183 | console.log((0, _getIterator3.default)(arr));
|
184 | ```
|
185 |
|
186 | This means is that you can seamlessly use these native built-ins and static methods
|
187 | without worrying about where they come from.
|
188 |
|
189 | **NOTE:** Instance methods such as `"foobar".includes("foo")` will **not** work.
|
190 |
|
191 | ### Helper aliasing
|
192 |
|
193 | Usually babel will place helpers at the top of your file to do common tasks to avoid
|
194 | duplicating the code around in the current file. Sometimes these helpers can get a
|
195 | little bulky and add unnecessary duplication across files. The `runtime`
|
196 | transformer replaces all the helper calls to a module.
|
197 |
|
198 | That means that the following code:
|
199 |
|
200 | ```javascript
|
201 | class Person {
|
202 | }
|
203 | ```
|
204 |
|
205 | usually turns into:
|
206 |
|
207 | ```javascript
|
208 | "use strict";
|
209 |
|
210 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
211 |
|
212 | var Person = function Person() {
|
213 | _classCallCheck(this, Person);
|
214 | };
|
215 | ```
|
216 |
|
217 | the `runtime` transformer however turns this into:
|
218 |
|
219 | ```javascript
|
220 | "use strict";
|
221 |
|
222 | var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
|
223 |
|
224 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
225 |
|
226 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
227 |
|
228 | var Person = function Person() {
|
229 | (0, _classCallCheck3.default)(this, Person);
|
230 | };
|
231 | ```
|