UNPKG

8.87 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
173Plugins are specified as an object with a `_parallelBabel` property:
174
175```js
176let plugin = {
177 _parallelBabel: {
178 requireFile: '/full/path/to/the/file',
179 useMethod: 'methodName',
180 buildUsing: 'buildFunction',
181 params: { ok: 'this object will be passed to buildFunction()' }
182 }
183};
184```
185
186Callbacks can be specified like plugins, or as functions with a
187`_parallelBabel` property:
188
189```js
190function callback() { /* do something */ };
191
192callback._parallelBabel = {
193 requireFile: '/full/path/to/the/file',
194 useMethod: 'methodName',
195 buildUsing: 'buildFunction',
196 params: { ok: 'this object will be passed to buildFunction()' }
197};
198```
199
200### requireFile (required)
201
202This property specifies the file to require in the worker process to create the
203plugin or callback. This must be given as an absolute path.
204
205```js
206const esTranspiler = require('broccoli-babel-transpiler');
207
208let somePlugin = {
209 _parallelBabel: {
210 requireFile: '/full/path/to/the/file'
211 }
212});
213
214let scriptTree = esTranspiler(inputTree, {
215 plugins: [
216 'transform-strict-mode', // plugins that are given as strings will automatically be parallelized
217 somePlugin
218 ]
219});
220```
221
222### useMethod (optional)
223
224This property specifies the method to use from the file that is required.
225
226If you have a plugin defined like this:
227
228```js
229// some_plugin.js
230
231module.exports = {
232 pluginFunction(babel) {
233 // do plugin things
234 }
235};
236```
237
238You can tell broccoli-babel-transpiler to use that function in the worker
239processes like so:
240
241```js
242const esTranspiler = require('broccoli-babel-transpiler');
243
244let somePlugin = {
245 _parallelBabel: {
246 requireFile: '/path/to/some_plugin',
247 useMethod: 'pluginFunction'
248 }
249});
250
251let scriptTree = esTranspiler(inputTree, {
252 plugins: [ somePlugin ]
253});
254```
255
256### buildUsing and params (optional)
257
258These properties specify a function to run to build the plugin (or callback),
259and any parameters to pass to that function.
260
261If the plugin needs to be built dynamically, you can do that like so:
262
263```js
264// some_plugin.js
265
266module.exports = {
267 buildPlugin(params) {
268 return doSomethingWith(params.text);
269 }
270};
271```
272
273This will tell the worker process to require the plugin and call the
274`buildPlugin` function with the `params` object as an argument:
275
276```js
277const esTranspiler = require('broccoli-babel-transpiler');
278
279let somePlugin = {
280 _parallelBabel: {
281 requireFile: '/path/to/some_plugin',
282 buildUsing: 'buildPlugin',
283 params: { text: 'some text' }
284 }
285});
286
287let scriptTree = esTranspiler(inputTree, {
288 plugins: [ somePlugin ]
289});
290```
291
292Note: If both `useMethod` and `buildUsing` are specified, `useMethod` takes
293precedence.
294
295### Number of jobs
296
297The number of parallel jobs defaults to the number of detected CPUs - 1.
298
299This can be changed with the `JOBS` environment variable:
300
301```sh
302JOBS=4 ember build
303```
304
305To disable parallelization:
306
307```sh
308JOBS=0 ember build
309JOBS=1 ember build
310```