UNPKG

13.3 kBMarkdownView Raw
1> This README is for babel-loader v8 + Babel v7
2> If you are using legacy Babel v6, see the [7.x branch](https://github.com/babel/babel-loader/tree/7.x) docs
3
4[![NPM Status](https://img.shields.io/npm/v/babel-loader.svg?style=flat)](https://www.npmjs.com/package/babel-loader)
5[![codecov](https://codecov.io/gh/babel/babel-loader/branch/main/graph/badge.svg)](https://codecov.io/gh/babel/babel-loader)
6
7<div align="center">
8 <a href="https://github.com/babel/babel">
9 <img src="https://rawgit.com/babel/logo/master/babel.svg" alt="Babel logo" width="200" height="200">
10 </a>
11 <a href="https://github.com/webpack/webpack">
12 <img src="https://webpack.js.org/assets/icon-square-big.svg" alt="webpack logo" width="200" height="200">
13 </a>
14</div>
15
16<h1 align="center">Babel Loader</h1>
17
18This package allows transpiling JavaScript files using [Babel](https://github.com/babel/babel) and [webpack](https://github.com/webpack/webpack).
19
20**Note**: Issues with the output should be reported on the Babel [Issues](https://github.com/babel/babel/issues) tracker.
21
22<h2 align="center">Install</h2>
23
24> webpack `4.x || 5.x` | babel-loader 8.x | babel 7.x
25
26```bash
27npm install -D babel-loader @babel/core @babel/preset-env webpack
28```
29
30<h2 align="center">Usage</h2>
31
32webpack documentation: [Loaders](https://webpack.js.org/loaders/)
33
34Within your webpack configuration object, you'll need to add the babel-loader to the list of modules, like so:
35
36```javascript
37module: {
38 rules: [
39 {
40 test: /\.m?js$/,
41 exclude: /node_modules/,
42 use: {
43 loader: 'babel-loader',
44 options: {
45 presets: [
46 ['@babel/preset-env', { targets: "defaults" }]
47 ]
48 }
49 }
50 }
51 ]
52}
53```
54
55### Options
56
57See the `babel` [options](https://babeljs.io/docs/en/options).
58
59You can pass options to the loader by using the [`options`](https://webpack.js.org/configuration/module/#ruleoptions--rulequery) property:
60
61```javascript
62module: {
63 rules: [
64 {
65 test: /\.m?js$/,
66 exclude: /node_modules/,
67 use: {
68 loader: 'babel-loader',
69 options: {
70 presets: [
71 ['@babel/preset-env', { targets: "defaults" }]
72 ],
73 plugins: ['@babel/plugin-proposal-class-properties']
74 }
75 }
76 }
77 ]
78}
79```
80
81This loader also supports the following loader-specific option:
82
83* `cacheDirectory`: Default `false`. When set, the given directory will be used to cache the results of the loader. Future webpack builds will attempt to read from the cache to avoid needing to run the potentially expensive Babel recompilation process on each run. If the value is set to `true` in options (`{cacheDirectory: true}`), the loader will use the default cache directory in `node_modules/.cache/babel-loader` or fallback to the default OS temporary file directory if no `node_modules` folder could be found in any root directory.
84
85* `cacheIdentifier`: Default is a string composed by the `@babel/core`'s version, the `babel-loader`'s version, the contents of `.babelrc` file if it exists, and the value of the environment variable `BABEL_ENV` with a fallback to the `NODE_ENV` environment variable. This can be set to a custom value to force cache busting if the identifier changes.
86
87* `cacheCompression`: Default `true`. When set, each Babel transform output will be compressed with Gzip. If you want to opt-out of cache compression, set it to `false` -- your project may benefit from this if it transpiles thousands of files.
88
89* `customize`: Default `null`. The path of a module that exports a `custom` callback [like the one that you'd pass to `.custom()`](#customized-loader). Since you already have to make a new file to use this, it is recommended that you instead use `.custom` to create a wrapper loader. Only use this if you _must_ continue using `babel-loader` directly, but still want to customize.
90
91* `metadataSubscribers`: Default `[]`. Takes an array of context function names. E.g. if you passed ['myMetadataPlugin'], you'd assign a subscriber function to `context.myMetadataPlugin` within your webpack plugin's hooks & that function will be called with `metadata`.
92
93## Troubleshooting
94
95### babel-loader is slow!
96
97Make sure you are transforming as few files as possible. Because you are probably matching `/\.m?js$/`, you might be transforming the `node_modules` folder or other unwanted source.
98
99To exclude `node_modules`, see the `exclude` option in the `loaders` config as documented above.
100
101You can also speed up babel-loader by as much as 2x by using the `cacheDirectory` option. This will cache transformations to the filesystem.
102
103### Some files in my node_modules are not transpiled for IE 11
104
105Although we typically recommend not compiling `node_modules`, you may need to when using libraries that do not support IE 11.
106
107For this, you can either use a combination of `test` and `not`, or [pass a function](https://webpack.js.org/configuration/module/#condition) to your `exclude` option. You can also use negative lookahead regex as suggested [here](https://github.com/webpack/webpack/issues/2031#issuecomment-294706065).
108
109```javascript
110{
111 test: /\.m?js$/,
112 exclude: {
113 and: [/node_modules/], // Exclude libraries in node_modules ...
114 not: [
115 // Except for a few of them that needs to be transpiled because they use modern syntax
116 /unfetch/,
117 /d3-array|d3-scale/,
118 /@hapi[\\/]joi-date/,
119 ]
120 },
121 use: {
122 loader: 'babel-loader',
123 options: {
124 presets: [
125 ['@babel/preset-env', { targets: "ie 11" }]
126 ]
127 }
128 }
129 }
130```
131
132### Babel is injecting helpers into each file and bloating my code!
133
134Babel uses very small helpers for common functions such as `_extend`. By default, this will be added to every file that requires it.
135
136You can instead require the Babel runtime as a separate module to avoid the duplication.
137
138The following configuration disables automatic per-file runtime injection in Babel, requiring `@babel/plugin-transform-runtime` instead and making all helper references use it.
139
140See the [docs](https://babeljs.io/docs/plugins/transform-runtime/) for more information.
141
142**NOTE**: You must run `npm install -D @babel/plugin-transform-runtime` to include this in your project and `@babel/runtime` itself as a dependency with `npm install @babel/runtime`.
143
144```javascript
145rules: [
146 // the 'transform-runtime' plugin tells Babel to
147 // require the runtime instead of inlining it.
148 {
149 test: /\.m?js$/,
150 exclude: /node_modules/,
151 use: {
152 loader: 'babel-loader',
153 options: {
154 presets: [
155 ['@babel/preset-env', { targets: "defaults" }]
156 ],
157 plugins: ['@babel/plugin-transform-runtime']
158 }
159 }
160 }
161]
162```
163
164#### **NOTE**: transform-runtime & custom polyfills (e.g. Promise library)
165
166Since [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-runtime) includes a polyfill that includes a custom [regenerator-runtime](https://github.com/facebook/regenerator/blob/master/packages/regenerator-runtime/runtime.js) and [core-js](https://github.com/zloirock/core-js), the following usual shimming method using `webpack.ProvidePlugin` will not work:
167
168```javascript
169// ...
170 new webpack.ProvidePlugin({
171 'Promise': 'bluebird'
172 }),
173// ...
174```
175
176The following approach will not work either:
177
178```javascript
179require('@babel/runtime/core-js/promise').default = require('bluebird');
180
181var promise = new Promise;
182```
183
184which outputs to (using `runtime`):
185
186```javascript
187'use strict';
188
189var _Promise = require('@babel/runtime/core-js/promise')['default'];
190
191require('@babel/runtime/core-js/promise')['default'] = require('bluebird');
192
193var promise = new _Promise();
194```
195
196The previous `Promise` library is referenced and used before it is overridden.
197
198One approach is to have a "bootstrap" step in your application that would first override the default globals before your application:
199
200```javascript
201// bootstrap.js
202
203require('@babel/runtime/core-js/promise').default = require('bluebird');
204
205// ...
206
207require('./app');
208```
209
210### The Node.js API for `babel` has been moved to `babel-core`.
211
212If you receive this message, it means that you have the npm package `babel` installed and are using the short notation of the loader in the webpack config (which is not valid anymore as of webpack 2.x):
213```javascript
214 {
215 test: /\.m?js$/,
216 loader: 'babel',
217 }
218```
219
220webpack then tries to load the `babel` package instead of the `babel-loader`.
221
222To fix this, you should uninstall the npm package `babel`, as it is deprecated in Babel v6. (Instead, install `@babel/cli` or `@babel/core`.)
223In the case one of your dependencies is installing `babel` and you cannot uninstall it yourself, use the complete name of the loader in the webpack config:
224```javascript
225 {
226 test: /\.m?js$/,
227 loader: 'babel-loader',
228 }
229```
230
231### Exclude libraries that should not be transpiled
232
233`core-js` and `webpack/buildin` will cause errors if they are transpiled by Babel.
234
235You will need to exclude them form `babel-loader`.
236
237```js
238{
239 "loader": "babel-loader",
240 "options": {
241 "exclude": [
242 // \\ for Windows, / for macOS and Linux
243 /node_modules[\\/]core-js/,
244 /node_modules[\\/]webpack[\\/]buildin/,
245 ],
246 "presets": [
247 "@babel/preset-env"
248 ]
249 }
250}
251```
252
253### Top level function (IIFE) is still arrow (on Webpack 5)
254
255That function is injected by Webpack itself _after_ running `babel-loader`. By default Webpack asumes that your target environment supports some ES2015 features, but you can overwrite this behavior using the `output.environment` Webpack option ([documentation](https://webpack.js.org/configuration/output/#outputenvironment)).
256
257To avoid the top-level arrow function, you can use `output.environment.arrowFunction`:
258
259```js
260// webpack.config.js
261module.exports = {
262 // ...
263 output: {
264 // ...
265 environment: {
266 // ...
267 arrowFunction: false, // <-- this line does the trick
268 },
269 },
270};
271```
272
273## Customize config based on webpack target
274
275Webpack supports bundling multiple [targets](https://webpack.js.org/concepts/targets/). For cases where you may want different Babel configurations for each target (like `web` _and_ `node`), this loader provides a `target` property via Babel's [caller](https://babeljs.io/docs/en/config-files#apicallercb) API.
276
277For example, to change the environment targets passed to `@babel/preset-env` based on the webpack target:
278
279```javascript
280// babel.config.js
281
282module.exports = api => {
283 return {
284 plugins: [
285 "@babel/plugin-proposal-nullish-coalescing-operator",
286 "@babel/plugin-proposal-optional-chaining"
287 ],
288 presets: [
289 [
290 "@babel/preset-env",
291 {
292 useBuiltIns: "entry",
293 // caller.target will be the same as the target option from webpack
294 targets: api.caller(caller => caller && caller.target === "node")
295 ? { node: "current" }
296 : { chrome: "58", ie: "11" }
297 }
298 ]
299 ]
300 }
301}
302```
303
304## Customized Loader
305
306`babel-loader` exposes a loader-builder utility that allows users to add custom handling
307of Babel's configuration for each file that it processes.
308
309`.custom` accepts a callback that will be called with the loader's instance of
310`babel` so that tooling can ensure that it using exactly the same `@babel/core`
311instance as the loader itself.
312
313In cases where you want to customize without actually having a file to call `.custom`, you
314may also pass the `customize` option with a string pointing at a file that exports
315your `custom` callback function.
316
317### Example
318
319```js
320// Export from "./my-custom-loader.js" or whatever you want.
321module.exports = require("babel-loader").custom(babel => {
322 function myPlugin() {
323 return {
324 visitor: {},
325 };
326 }
327
328 return {
329 // Passed the loader options.
330 customOptions({ opt1, opt2, ...loader }) {
331 return {
332 // Pull out any custom options that the loader might have.
333 custom: { opt1, opt2 },
334
335 // Pass the options back with the two custom options removed.
336 loader,
337 };
338 },
339
340 // Passed Babel's 'PartialConfig' object.
341 config(cfg) {
342 if (cfg.hasFilesystemConfig()) {
343 // Use the normal config
344 return cfg.options;
345 }
346
347 return {
348 ...cfg.options,
349 plugins: [
350 ...(cfg.options.plugins || []),
351
352 // Include a custom plugin in the options.
353 myPlugin,
354 ],
355 };
356 },
357
358 result(result) {
359 return {
360 ...result,
361 code: result.code + "\n// Generated by some custom loader",
362 };
363 },
364 };
365});
366```
367
368```js
369// And in your Webpack config
370module.exports = {
371 // ..
372 module: {
373 rules: [{
374 // ...
375 loader: path.join(__dirname, 'my-custom-loader.js'),
376 // ...
377 }]
378 }
379};
380```
381
382### `customOptions(options: Object): { custom: Object, loader: Object }`
383
384Given the loader's options, split custom options out of `babel-loader`'s
385options.
386
387
388### `config(cfg: PartialConfig): Object`
389
390Given Babel's `PartialConfig` object, return the `options` object that should
391be passed to `babel.transform`.
392
393
394### `result(result: Result): Result`
395
396Given Babel's result object, allow loaders to make additional tweaks to it.
397
398
399## License
400[MIT](https://couto.mit-license.org/)