UNPKG

8.96 kBMarkdownView Raw
1# broccoli-babel-transpiler
2
3[![Build Status](https://travis-ci.org/babel/broccoli-babel-transpiler.svg?branch=master)](https://travis-ci.org/babel/broccoli-babel-transpiler)
4[![Build status](https://ci.appveyor.com/api/projects/status/a0nbd84m1x4y5fp5?svg=true)](https://ci.appveyor.com/project/embercli/broccoli-babel-transpiler)
5
6
7A [Broccoli](https://github.com/broccolijs/broccoli) plugin which transpiles ES6 to readable ES5 (and much more) by using [Babel](https://github.com/babel/babel).
8
9## How to install?
10
11```sh
12$ npm install broccoli-babel-transpiler --save-dev
13```
14
15## How to use?
16
17In your `Brocfile.js`:
18
19```js
20const esTranspiler = require('broccoli-babel-transpiler');
21const scriptTree = esTranspiler(inputTree, babelOptions);
22```
23
24Note that, since Babel 6 (and v6 of this plugin), you need to be specific as to
25what your transpilation target is. Running `esTranspiler` with empty options
26will not transpile anything. You will need:
27
28 * Explicit options, such as `presets`. See available [options](https://babeljs.io/docs/usage/options) at Babel's GitHub repo.
29 * Babel plugins that implement the transforms you require.
30
31For a quick running example, install this plugin:
32
33```sh
34$ npm install babel-preset-env
35```
36
37And then run the transform like this:
38
39```js
40let scriptTree = babel(inputTree, {
41 presets: [
42 ['env', {
43 'targets': {
44 'browsers': ['last 2 versions']
45 }
46 }]
47 ]
48});
49```
50
51### Examples
52
53You'll find three example projects using this plugin in the repository
54[broccoli-babel-examples](https://github.com/givanse/broccoli-babel-examples).
55Each one of them builds on top of the previous example so you can progess from
56bare minimum to ambitious development.
57
58 * [es6-fruits](https://github.com/givanse/broccoli-babel-examples/tree/master/es6-fruits) - Execute a single ES6 script.
59 * [es6-website](https://github.com/givanse/broccoli-babel-examples/tree/master/es6-website) - Build a simple website.
60 * [es6-modules](https://github.com/givanse/broccoli-babel-examples/tree/master/es6-modules) - Handle modules and unit tests.
61
62## About source map
63
64Currently this plugin only supports inline source map. If you need
65separate source map feature, you're welcome to submit a pull request.
66
67## Advanced usage
68
69`filterExtensions` is an option to limit (or expand) the set of file extensions
70that will be transformed.
71
72The default `filterExtension` is `js`
73
74```js
75const esTranspiler = require('broccoli-babel-transpiler');
76let scriptTree = esTranspiler(inputTree, {
77 filterExtensions:['js', 'es6'] // babelize both .js and .es6 files
78});
79```
80
81`targetExtension` is an option to specify the extension of the output files
82
83The default `targetExtension` is `js`
84
85```js
86const esTranspiler = require('broccoli-babel-transpiler');
87let scriptTree = esTranspiler(inputTree, {
88 targetExtension: 'module.js' // create output files with module.js extension
89});
90```
91
92## Polyfill
93
94In order to use some of the ES6 features you must include the Babel
95[polyfill](http://babeljs.io/docs/usage/polyfill/#usage-in-browser).
96
97You don't always need this, review which features need the polyfill here: [ES6
98Features](https://babeljs.io/docs/learn-es6).
99
100```js
101const esTranspiler = require('broccoli-babel-transpiler');
102let scriptTree = esTranspiler(inputTree, { browserPolyfill: true });
103```
104
105## Plugins
106
107Use of custom plugins works similarly to `babel` itself. You would pass a
108`plugins` array in `options`:
109
110```js
111const esTranspiler = require('broccoli-babel-transpiler');
112const applyFeatureFlags = require('babel-plugin-feature-flags');
113
114let featureFlagPlugin = applyFeatureFlags({
115 import: { module: 'ember-metal/features' },
116 features: {
117 'ember-metal-blah': true
118 }
119});
120
121let scriptTree = esTranspiler(inputTree, {
122 plugins: [
123 featureFlagPlugin
124 ]
125});
126```
127
128### Caching
129
130broccoli-babel-transpiler uses a persistent cache to enable rebuilds to be
131significantly faster (by avoiding transpilation for files that have not
132changed). However, since a plugin can do many things to affect the transpiled
133output it must also influence the cache key to ensure transpiled files are
134rebuilt
135if the plugin changes (or the plugins configuration).
136
137In order to aid plugin developers in this process, broccoli-babel-transpiler
138will invoke two methods on a plugin so that it can augment the cache key:
139
140* `cacheKey` - This method is used to describe any runtime information that may
141 want to invalidate the cached result of each file transpilation. This is
142 generally only needed when the configuration provided to the plugin is used
143 to modify the AST output by a plugin like `babel-plugin-filter-imports`
144 (module
145 exports to strip from a build), `babel-plugin-feature-flags` (configured
146 features and current status to strip or embed in a final build), or
147 `babel-plugin-htmlbars-inline-precompile` (uses `ember-template-compiler.js`
148 to compile inlined templates).
149* `baseDir` - This method is expected to return the plugins base dir. The
150 provided `baseDir` is used to ensure the cache is invalidated if any of the
151 plugin's files change (including its deps). Each plugin should implement
152 `baseDir` as: `Plugin.prototype.baseDir = function() { return \_\_dirname;
153 };`.
154
155## Parallel Transpilation
156
157broccoli-babel-transpiler can run multiple babel transpiles in parallel using a
158pool of workers, to take advantage of multi-core systems. Because these workers
159are separate processes, the plugins and callback functions that are normally
160passed as options to babel must be specified in a serializable form.
161To enable this parallelization there is an API to tell the worker how to
162construct the plugin or callback in its process.
163
164To ensure a build remains parallel safe, one can set the
165`throwUnlessParallelizable` option to true (defaults to false). This will cause
166an error to be thrown, if parallelization is not possible due to an
167incompatible babel plugin.
168
169```js
170new Babel(input, { throwUnlessParallelizable: true | false });
171```
172
173Alternatively, an environment variable can be set:
174
175```sh
176THROW_UNLESS_PARALLELIZABLE=1 node build.js
177```
178
179Plugins are specified as an object with a `_parallelBabel` property:
180
181```js
182let plugin = {
183 _parallelBabel: {
184 requireFile: '/full/path/to/the/file',
185 useMethod: 'methodName',
186 buildUsing: 'buildFunction',
187 params: { ok: 'this object will be passed to buildFunction()' }
188 }
189};
190```
191
192Callbacks can be specified like plugins, or as functions with a
193`_parallelBabel` property:
194
195```js
196function callback() { /* do something */ };
197
198callback._parallelBabel = {
199 requireFile: '/full/path/to/the/file',
200 useMethod: 'methodName',
201 buildUsing: 'buildFunction',
202 params: { ok: 'this object will be passed to buildFunction()' }
203};
204```
205
206### requireFile (required)
207
208This property specifies the file to require in the worker process to create the
209plugin or callback. This must be given as an absolute path.
210
211```js
212const esTranspiler = require('broccoli-babel-transpiler');
213
214let somePlugin = {
215 _parallelBabel: {
216 requireFile: '/full/path/to/the/file'
217 }
218});
219
220let scriptTree = esTranspiler(inputTree, {
221 plugins: [
222 'transform-strict-mode', // plugins that are given as strings will automatically be parallelized
223 somePlugin
224 ]
225});
226```
227
228### useMethod (optional)
229
230This property specifies the method to use from the file that is required.
231
232If you have a plugin defined like this:
233
234```js
235// some_plugin.js
236
237module.exports = {
238 pluginFunction(babel) {
239 // do plugin things
240 }
241};
242```
243
244You can tell broccoli-babel-transpiler to use that function in the worker
245processes like so:
246
247```js
248const esTranspiler = require('broccoli-babel-transpiler');
249
250let somePlugin = {
251 _parallelBabel: {
252 requireFile: '/path/to/some_plugin',
253 useMethod: 'pluginFunction'
254 }
255});
256
257let scriptTree = esTranspiler(inputTree, {
258 plugins: [ somePlugin ]
259});
260```
261
262### buildUsing and params (optional)
263
264These properties specify a function to run to build the plugin (or callback),
265and any parameters to pass to that function.
266
267If the plugin needs to be built dynamically, you can do that like so:
268
269```js
270// some_plugin.js
271
272module.exports = {
273 buildPlugin(params) {
274 return doSomethingWith(params.text);
275 }
276};
277```
278
279This will tell the worker process to require the plugin and call the
280`buildPlugin` function with the `params` object as an argument:
281
282```js
283const esTranspiler = require('broccoli-babel-transpiler');
284
285let somePlugin = {
286 _parallelBabel: {
287 requireFile: '/path/to/some_plugin',
288 buildUsing: 'buildPlugin',
289 params: { text: 'some text' }
290 }
291});
292
293let scriptTree = esTranspiler(inputTree, {
294 plugins: [ somePlugin ]
295});
296```
297
298Note: If both `useMethod` and `buildUsing` are specified, `useMethod` takes
299precedence.
300
301### Number of jobs
302
303The number of parallel jobs defaults to the number of detected CPUs - 1.
304
305This can be changed with the `JOBS` environment variable:
306
307```sh
308JOBS=4 ember build
309```
310
311To disable parallelization:
312
313```sh
314JOBS=1 ember build
315```