npm package: @putzisan/babel-config
Description: [babel7](https://new.babeljs.io/docs/en/next/babel-core.html) is used equally for all build+test+develop.
Author: PS
Latest version: 0.0.0

# babel

[babel7](https://new.babeljs.io/docs/en/next/babel-core.html) is used equally for all build+test+develop.

## `babel.config.js`

Babel is configured via the [babel.config.js](https://babeljs.io/docs/en/next/babelconfigjs)-file. The `process.env.NODE_ENV`-variable is used to determine which plugins and presets should be added.

### presets and plugins

[Presets](https://new.babeljs.io/docs/en/next/plugins.html#presets) are a predefined set of [plugins](https://new.babeljs.io/docs/en/next/plugins.html), see [babel-dependencies](#babel-dependencies) for the individual presets/plugins we use.

[Plugin/Preset Ordering](https://new.babeljs.io/docs/en/next/plugins.html#plugin-preset-ordering):

- Plugins run before Presets
- Plugin ordering is first to last
- Preset ordering is reversed (last to first)

### `production`-specific options

- add [@babel/plugin-transform-runtime](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html), see [babel-helper-functions via babel-runtime for smaller bundle-size](#babel-helper-functions-via-babel-runtime-for-smaller-bundle-size)
- turns off the [`development`](https://new.babeljs.io/docs/en/next/babel-preset-react.html#development)-option in [@babel/preset-react](https://new.babeljs.io/docs/en/next/babel-preset-react.html)

### `development`-specific options

- do not include the [@babel/preset-env](https://new.babeljs.io/docs/en/next/babel-preset-env.html), you will use a new browser for dev, so no need to waste compile-time with this preset during dev
- add [react-hot-loader/babel](https://github.com/gaearon/react-hot-loader), look at [react-hot-loader](#react-hot-loader) for more information.

### `test`-specific options

Customizations for jest, since jest ES6 cannot `import`/`export` and does not understand dynamic imports, see [jest-documentation](https://jestjs.io/docs/en/webpack.html#using-with-webpack-2):

- ES6-exports to commonjs: `@babel/preset-env` will be adapted from `"modules": false` to `"modules": "commonjs"`
- dynamic imports: use [babel-plugin-dynamic-import-node](https://github.com/airbnb/babel-plugin-dynamic-import-node) by AirBnb instead of [@babel/plugin-syntax-dynamic-import](https://new.babeljs.io/docs/en/next/babel-plugin-syntax-dynamic-import.html)

## babel-helper-functions via babel-runtime for smaller bundle-size

Babel injects [small helper-functions](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html#why) like `_extend`, when needed. With [@babel/plugin-transform-runtime](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html) the code is not copied in every file, but the transform-runtime-plugin will inject referneces to the [@babel/runtime](https://babeljs.io/docs/en/next/babel-runtime.html)-package, which holds the implementations of the helper-functions (["Helper aliasing"](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html#helper-aliasing)). This will result in a smaller bundle. The [`"useESModules": true`-option ](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html#useesmodules) will use ES6-modules (`import`/`export`) instead of the implementations with commonjs (`require`/`module.exports`).

Please note that the [@babel/plugin-transform-runtime](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html) can also perform other transformations:

- [`corejs`](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html#corejs) will [polyfill new built-ins (Promise, Map, ...)](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html#core-js-aliasing) via the [core-js](https://github.com/zloirock/core-js#babel)-library
- [`regenerator`](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html#regenerator) will transform [generator-functions (`function*`)](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/function*) into [ES5-Code with a local regenerator-runtime](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html#regenerator-aliasing)

In my opinion it is not a good idea to use these options, because the inserted transformations [can take up a lot of space](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime#core-js-aliasing) and it is very likely that others also use polyfills, so it may be that a feature is polyfilled by several different libraries which bloats your bundle. If you are developing a library, it is best not to use features that require polyfills at all. If really necessary, use [ponyfills](https://github.com/sindresorhus/ponyfill) and document the use.

## polyfills

In `src/index.tsx` the first line loads a polyfill-script (`import './bootstrap/polyfills';`), so that the app also runs under Internet Explorer 11 (IE11). Following polyfills are included:

- [`Promise`](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise) via [this promise-library](https://github.com/then/promise) (Promises are required for [code-splitting via dynamic imports](https://webpack.js.org/guides/code-splitting/#dynamic-imports))
- [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) via [this object-assign-library](https://github.com/sindresorhus/object-assign) (`Object.assign` is needed for the [@babel/plugin-proposal-object-rest-spread with the `useBuiltIns`-option](https://babeljs.io/docs/en/next/babel-plugin-proposal-object-rest-spread.html#usebuiltins) and in some libraries (e.g. [react-loadable](https://github.com/jamiebuilds/react-loadable/blob/master/src/index.js#L105)) but not included in IE11)

Both polyfills together increase the bundle-size by ~ 5kb. If you think you do not need this polyfills you can remove them. If you need other polyfills, because you use new features or have to support very old browsers, you should attach them in `src/bootstrap/polyfills.js`.

### polyfills via babel-polyfill (not recommended)

To stop thinking about polyfills you can automate this process with [babel-polyfill](https://babeljs.io/docs/en/next/babel-polyfill). Similar to [@babel/plugin-transform-runtime with the `corejs`-option](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime#core-js-aliasing), polyfills via [core-js](https://github.com/zloirock/core-js#babel) are added for older browsers. In contrast to runtime, the polyfills are loaded globally into the application (which is not recommended for libraries).

You can then additionaly use the [`useBuiltIns`-option of the babel-preset-env](https://babeljs.io/docs/en/next/babel-preset-env#usebuiltins):

- `useBuiltIns: 'usage'`: Adds specific imports for polyfills when they are used in each file. We take advantage of the fact that a bundler will load the same polyfill only once. Be aware that this will not polyfill usages in `node_modules`
- `useBuiltIns: 'entry'`: You need to import `@babel/polyfill` in your entry-file once, babel will transform this import to only include imports needed by the specified [preset-env `target`-option](https://babeljs.io/docs/en/next/babel-preset-env#targets); At the moment (as of 13.08.2018) this is for `browsers: ['>0.25%']` still over 80 kb

I would not recommend the use of babel-polyfill since:

- either significantly too many polyfills are imported (library standalone or with `useBuiltIns: 'entry'`) or
- using `useBuiltIns: 'usage'` the polyfills are incosistent (they are included locally per file but change the global namespace) and only functions used in your code are analyzed (since used `node_modules`s are not examined), außerdem ist auch mit dieser Methode
  - Also with this method the resulting package is bigger than if you install the polyfills yourself as [described above](#polyfills)
  - For the example app only the two polyfills [mentioned above](#polyfills) are needed to run under IE11, the bundle size was still ~ 14 kb bigger and I had to install the required imports manually into `index.ts`, because preset-env did not recognize that for the dynamic `import()` Promise must polyfill and for React-Loadable `Object.assign`

## babel-dependencies

| package                                                                                                                    | description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [@babel/core](https://new.babeljs.io/docs/en/next/babel-core.html)                                                         | peer-dependency for everything else                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| [@babel/plugin-proposal-class-properties](https://new.babeljs.io/docs/en/next/babel-plugin-proposal-class-properties.html) | [see proposal](https://github.com/tc39/proposal-class-fields), so that ES6 class fields can not only be set in the constructor; the [`"loose": true`-option](https://new.babeljs.io/docs/en/next/babel-plugin-proposal-class-properties.html#loose) will assign the properties via assignment expressions instead of `Object.defineProperty` which results in less code                                                                                                                                                                                                                                                                                                                                   |
| [@babel/plugin-proposal-object-rest-spread](https://babeljs.io/docs/en/next/babel-plugin-proposal-object-rest-spread.html) | The [Object-React-Operator (`...`)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) is not natively supported by preset-env.<br />The rest operator works in TypeScript files without this transformation because the [TypeScript compiler has been compiling it to ES5 code since TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#object-spread-and-rest).<br />The [`useBuiltIns: true`-Option](https://babeljs.io/docs/en/next/babel-plugin-proposal-object-rest-spread.html#usebuiltins) transforms it to `Object.assign`-calls, [make sure to include a polyfill for older browsers (IE 11)](#polyfills) |
| [@babel/plugin-syntax-dynamic-import](https://new.babeljs.io/docs/en/next/babel-plugin-syntax-dynamic-import.html)         | only [Syntax-Plugin](https://new.babeljs.io/docs/en/next/plugins.html#syntax-plugins)! so babel understands dynamic imports, [which webpack uses for code-splitting](https://webpack.js.org/guides/code-splitting/#dynamic-imports)                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| [@babel/plugin-transform-runtime](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html)                     | Babel-helpers and -polyfills will use [@babel/runtime](https://babeljs.io/docs/en/next/babel-runtime.html), without this babel copies the needed helper into every single file when needed, for more information [visit their documentation](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html); the [`"useESModules": true`-option ](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html#useesmodules) will use ES6-modules with `import`/`export`                                                                                                                                                                                                                     |
| [@babel/runtime](https://babeljs.io/docs/en/next/babel-runtime.html)                                                       | Babel will inject this dependency in your code when needed via [@babel/plugin-transform-runtime](https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html), see upper line                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| [@babel/preset-env](https://new.babeljs.io/docs/en/next/babel-preset-env.html)                                             | ES>5 to ES5, should always run as the last transformation, so it [should always remain the first `presets`-entry](https://new.babeljs.io/docs/en/next/plugins.html#plugin-preset-ordering)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| [@babel/preset-react](https://new.babeljs.io/docs/en/next/babel-preset-react.html)                                         | JSX to ES6;<br />[`useBuiltIns`-option](https://babeljs.io/docs/en/next/babel-preset-react#usebuiltins) will passed through the [`useBuiltIns`-option in @babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/next/babel-plugin-transform-react-jsx.html#usebuiltins) => "When spreading props, use Object.assign directly instead of Babel's extend helper."<br />[`development`-option](https://babeljs.io/docs/en/next/babel-preset-react#development) will add debug-informations, [turned off in production](#production-specific-options)                                                                                                                                                  |
| [@babel/preset-typescript](https://new.babeljs.io/docs/en/next/babel-preset-typescript.html)                               | TS/TSX to ES6/JSX                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| [babel-plugin-dynamic-import-node](https://github.com/airbnb/babel-plugin-dynamic-import-node)                             | the only one not by babel itself but by airbnb, only for jest-tests, see [jest-declaration](https://jestjs.io/docs/en/webpack.html#using-with-webpack-2)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

## further babel-dependencies

| package                                                                        | description                                                                                   |
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
| [babel-core@7.0.0-bridge.0](https://github.com/babel/babel-bridge)             | for jest-test, [siehe jest-doku](https://jestjs.io/docs/en/getting-started.html#using-babel)  |
| [babel-jest](https://github.com/facebook/jest/tree/master/packages/babel-jest) | so that jest also uses the babel-transformations                                              |
| [babel-loader@8.0.0-beta.4](https://github.com/babel/babel-loader)             | to transform files via webpack, new babel-load-v8 must be used with new babel7                |
| [react-hot-loader/babel](https://github.com/gaearon/react-hot-loader)          | babel extension for hot-loading to work with react, see [react-hot-loader](#react-hot-loader) |