From 597d895cf3b22b2dd6404534ae8335c3de42b30f Mon Sep 17 00:00:00 2001 From: Tiago Rodrigues Date: Mon, 11 Jan 2016 15:26:07 +0100 Subject: [PATCH 1/2] Documentation for babel-plugin-transform-runtime Based on https://github.com/babel/babel.github.io/blob/862b43db93e48762671267034a50c30c00e433e2/docs/usage/runtime.md Related to https://github.com/babel/babel.github.io/issues/674 and https://github.com/babel/babel.github.io/issues/491 --- .../babel-plugin-transform-runtime/README.md | 177 +++++++++++++++++- 1 file changed, 175 insertions(+), 2 deletions(-) diff --git a/packages/babel-plugin-transform-runtime/README.md b/packages/babel-plugin-transform-runtime/README.md index 700676dee6..efd734b19d 100644 --- a/packages/babel-plugin-transform-runtime/README.md +++ b/packages/babel-plugin-transform-runtime/README.md @@ -1,6 +1,18 @@ # babel-plugin-transform-runtime -Externalise references to helpers and builtins, automatically polyfilling your code without polluting globals +Externalise references to helpers and builtins, automatically polyfilling your code without polluting globals. + +## 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 runtime transformer 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 use [babel-polyfill](https://github.com/contentful/contentful-space-sync/releases/tag/v3.0.0) 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. ## Installation @@ -8,11 +20,15 @@ Externalise references to helpers and builtins, automatically polyfilling your c $ npm install babel-plugin-transform-runtime ``` +It is also recommended you install the `babel-runtime` package as a +runtime dependency, if you haven't already, as the transformed code will +require that package. See the examples below for more details. + ## Usage ### Via `.babelrc` (Recommended) -**.babelrc** +Add the following line to your `.babelrc` file: ```json { @@ -33,3 +49,160 @@ require("babel-core").transform("code", { plugins: ["transform-runtime"] }); ``` + +## Technical details + +The `runtime` transformer plugin does three things: + +* Automatically requires `babel-runtime/regenerator` when you use generators/async functions. +* Automatically requires `babel-runtime/core-js` and maps ES6 static methods and built-ins. +* Removes the inline babel helpers and uses the module `babel-runtime/helpers` instead. + +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: + +```javascript +function* foo() { + +} +``` + +the following is generated: + +```javascript +"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 as then you have to include the regenerator runtime which +pollutes the global scope. + +Instead what the `runtime` transformer does it compile that to: + +```javascript +"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 regeneratorRuntime.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. + +What the `runtime` transformer does is transform the following: + +```javascript +var sym = Symbol(); + +var promise = new Promise; + +console.log(arr[Symbol.iterator]()); +``` + +into the following: + +```javascript +"use strict"; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _promise = require("babel-runtime/core-js/promise"); + +var _promise2 = _interopRequireDefault(_promise); + +var _symbol = require("babel-runtime/core-js/symbol"); + +var _symbol2 = _interopRequireDefault(_symbol); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var sym = (0, _symbol2.default)(); + +var promise = new _promise2.default(); + +console.log((0, _getIterator3.default)(arr)); +``` + +This means is that you can seamlessly use these native built-ins and static methods +without worrying about where they come from. + +**NOTE:** Instance methods such as `"foobar".includes("foo")` will **not** work. + +### 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: + +```javascript +class Person { +} +``` + +usually turns into: + +```javascript +"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: + +```javascript +"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); +}; +``` From 61bf94afdbaa2781bdeaa6b627b10b1176cf190f Mon Sep 17 00:00:00 2001 From: Tiago Rodrigues Date: Wed, 3 Feb 2016 10:07:55 +0100 Subject: [PATCH 2/2] Fix bad link due to copypaste failure --- packages/babel-plugin-transform-runtime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/babel-plugin-transform-runtime/README.md b/packages/babel-plugin-transform-runtime/README.md index efd734b19d..8f51d42105 100644 --- a/packages/babel-plugin-transform-runtime/README.md +++ b/packages/babel-plugin-transform-runtime/README.md @@ -8,7 +8,7 @@ Babel uses very small helpers for common functions such as `_extend`. By default This is where the runtime transformer 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 use [babel-polyfill](https://github.com/contentful/contentful-space-sync/releases/tag/v3.0.0) 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. +Another purpose of this transformer is to create a sandboxed environment for your code. If you use [babel-polyfill](https://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. The transformer will alias these built-ins to `core-js` so you can use them seamlessly without having to require the polyfill.