Skip to content

Commit

Permalink
feat: upgrade to babel 7
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the way the preset is different

Closes #26
  • Loading branch information
satazor committed Feb 12, 2019
1 parent 9c8e865 commit a5223bd
Show file tree
Hide file tree
Showing 13 changed files with 4,101 additions and 5,435 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ language: node_js
node_js:
- "node"
- "lts/*"
- '8'
- '6'
# Report coverage
after_success:
- "npm i codecov"
Expand Down
118 changes: 88 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@

## Installation

`$ npm install babel-preset-moxy --save-dev`

You might need to also install [babel-cli](https://www.npmjs.com/package/babel-cli) as a dev dependency.
```ssh
$ npm install babel-preset-moxy @babel/core --save-dev
```

Please read the [Caveats](#caveats) section because it contains important notes that you should be aware of.


## Motivation
### Motivation

If you are developing a project that uses new ECMAScript language features and must work on targets that do not yet support them, you have to transpile your code. This preset provides a shareable Babel config as a preset that should be used across those projects at MOXY.

Expand All @@ -39,27 +39,48 @@ If you are developing a project that uses new ECMAScript language features and m
- Uses [add-module-exports](https://github.com/59naga/babel-plugin-add-module-exports) to get around [babel#2212](https://github.com/babel/babel/issues/2212)
- Enables [babel-plugin-lodash](https://github.com/lodash/babel-plugin-lodash)

Please note that **there are few reasons** to use Babel when you are developing a library that **only targets Node.js** because the latest LTS and current version support [99%](http://node.green/) of ES8.
Please note that **there are few reasons** to use Babel when you are developing a library that **only targets Node.js** because the latest LTS and current version support [99%](http://node.green/) of ES8. There are a few exceptions though, such as if you are using JSX or targeting older Node.js versions.


## Usage

Create `.babelrc` at the root of your project:
### 1. Choose a preset-type

There's two preset types available for you to use:

- For libraries: Use the `lib` type in case you are developing a library to be consumed by others
- For end-projects: Use the `end-project` type in case you developing a top-level project, such as an Web Application, a Node.js API or CLI

### 2. Setup babel within your project

The way babel is configured depends on the type of project you are developing and the tooling you are using. Below, there's instructions for common scenarios:

#### Standard project

> If you don't use a bundler within your project, this is the setup guide you should follow
Create `.babelrc` at the root of your project, replacing `preset-type` with the preset type you chose:

```json
{
"presets": ["moxy"]
"presets": ["moxy/<preset-type>"]
}
```

...or with options:

```json
{
"presets": [["moxy", { "react": true }]]
"presets": [["moxy/<preset-type>", { "react": true }]]
}
```

Install [@babel/cli](https://www.npmjs.com/package/@babel/cli) as a dev dependency because we will need it for the build script:

```ssh
$ npm install @babel/cli --save-dev
```

Set up your `package.json` like this:

```json
Expand All @@ -76,32 +97,47 @@ Set up your `package.json` like this:
}
```

And finally create `src/index.js` and start coding!


Available options:

| Name | Description | Type | Default |
| ------ | ------------- | -------- | ------- |
| env | The environment (`development`, `production` or `test`) | string | Based on `process.env.NODE_ENV` |
| targets | The output targets, see bellow for a more detailed explanation | Array/[Object](https://www.npmjs.com/package/babel-preset-env#targets) | ['browsers', 'node']
| react | Adds support for [React](https://reactjs.org/) | boolean | false |
| modules | Transform ES6 module syntax to another module type | [string/boolean](https://www.npmjs.com/package/babel-preset-env#modules) | Based on `process.env.BABEL_ENV` |
| namedDefaultExport | Use [add-module-exports](https://github.com/59naga/babel-plugin-add-module-exports) plugin to get around [babel/babel#2212](https://github.com/babel/babel/issues/2212) | boolean | true if modules is `commonjs` |
| lodash | Transform to cherry-pick Lodash modules | boolean/[Object](https://github.com/lodash/babel-plugin-lodash#usage) | true |
Create `src/index.js` and happy coding!

The `env`'s default value respects `process.env.NODE_ENV` and falls back to `production` if none are set. When env is `production`, some plugins that perform code optimization will be enabled.
#### Webpack based project

The `modules` default value is `commonjs` unless `process.env.BABEL_ENV` is set to `es`.
> If you are using the Webpack bundler
Tweak your webpack config JS rule like so:

### `targets` option
```js
{
test: /\.js$/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true, // Improve performance
presets: [
[require.resolve('babel-preset-moxy'), {
targets: ['browsers'],
react: true,
modules: false,
}],
]
},
},
]
}
```

The targets option has a very important role. By default, its value is `['browsers', 'node']` which means that the compiled code will work in both the Browser and in Node.js.
It's important that you compile all the `node_modules` folder so that babel's `preset-env` ensures that all libraries are compiled to the targets we support. You may read more about this in the [`targets`](#targets-option) option description.

When `browsers` is specified, the compiled code will work on browsers that are supported by [Google's browser support policy](https://github.com/awkaiser/browserslist-config-google). When `node` is specified, the compiled code will work on the last LTS or higher (currently `v8.9`).
### 3. Tweak the options

If you are developing a library or application that has different requirements in terms of browser or node support, you may specify the [targets](https://www.npmjs.com/package/babel-preset-env#targets) yourself as an object.
| Name | Description | Type | Default | in `lib` | in `end-project` |
| ------ | ------------- | -------- | ------- | ------------ | ------------ |
| react | Adds support for [React](https://reactjs.org/) | boolean | false |||
| lodash | Transform to cherry-pick Lodash modules | boolean/[Object](https://github.com/lodash/babel-plugin-lodash#usage) | true |||
| modules | Transform ES6 module syntax to another module type | [string/boolean](https://www.npmjs.com/package/babel-preset-env#modules) | Based on `process.env.BABEL_ENV` |||
| targets | The output targets, see bellow for a more detailed explanation | Array/[Object](https://www.npmjs.com/package/babel-preset-env#targets) | ['browsers', 'node'] |||
| env | The environment (`development`, `production` or `test`) | string | Based on `process.env.NODE_ENV` |||
| namedDefaultExport | Use [add-module-exports](https://github.com/59naga/babel-plugin-add-module-exports) plugin to get around [babel/babel#2212](https://github.com/babel/babel/issues/2212) | boolean | true if modules is `commonjs` |||

### `lodash` option

Expand All @@ -121,6 +157,26 @@ For instance, to have smaller bundles when using [recompose](https://github.com/
}
```

### `targets` option

The targets option has a very important role. By default, its value is `['browsers', 'node']` which means that the compiled code will work in both the Browser and in Node.js.

When `browsers` is specified, the compiled code will work on browsers that are supported by [Google's browser support policy](https://github.com/awkaiser/browserslist-config-google). When `node` is specified, the compiled code will work on the last LTS or higher (currently `v8.9`).

If your project has different requirements in terms of browser or node support, you may specify the [targets](https://www.npmjs.com/package/babel-preset-env#targets) yourself as an object.

This option is only available for the `end-project` because libraries [should not be compiled](https://github.com/parcel-bundler/parcel/pull/559#discussion_r161926651) down to older versions of JavaScript. Instead, applications should be compiling everything, including `node_modules`, based on what targets they need to support.

### `env` option

The `env`'s default value respects `process.env.NODE_ENV` and falls back to `production` if none are set. When env is `production`, some plugins that perform code optimization will be enabled.

The `modules` default value is `commonjs` unless `process.env.BABEL_ENV` is set to `es`. Similar to the `targets` option, this option is only available for the `end-project` because only know the environment we are targeting at the top-level .


### 4. Read the Caveats

No, seriously. Read the [Caveats](#caveats) section as it contains crucial information and might require you to do a few more steps.


## Caveats
Expand All @@ -137,7 +193,7 @@ For this reason, you, as an author, should state in the README of your library t

#### For applications

Simply include `import 'babel-polyfill';` or `import 'core-js';` at the top of your main app file.
Simply include `import 'babel-polyfill';` at the top of your main app file.
Those statements will be replaced with the necessary polyfills based on node/browser support.

```js
Expand Down Expand Up @@ -179,8 +235,10 @@ As an example, UglifyJS v2 only understands ES5 syntax but [UglifyJS v3](https:/

## Tests

`$ npm test`
`$ npm test -- --watch` during development
```sh
$ npm test
$ npm test -- --watch # during development
```


## License
Expand Down
57 changes: 57 additions & 0 deletions end-project.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
'use strict';

const addReactSupport = require('./lib/react');
const addLodashSupport = require('./lib/lodash');

module.exports = (context, options) => {
options = Object.assign({
modules: process.env.BABEL_ENV === 'es' ? false : 'commonjs', // Usually set to `commonjs` or `false`
react: false,
lodash: true,
targets: ['browsers', 'node'], // Can be an array with `browsers` and/or `node` or an object
env: process.env.NODE_ENV || 'production',
}, options);

const config = {
presets: [],
plugins: [],
};

// The `preset-env` will activate the necessary features based on our targets
// It's no longer necessary to add `es2015`, `es2016`, etc manually
config.presets.push([require.resolve('@babel/preset-env'), {
// Replaces `import 'babel-polyfill';` with only the polyfills that are
// actually required based on the targets
useBuiltIns: 'entry',
// Produce less and more readable code (although not as faithful to the semantics)
loose: true,
// Set modules options
modules: options.modules,
// Set the browser support to be the same used by Google (https://www.npmjs.com/package/browserslist-config-google)
// Set Nodejs target to be the latest LTS
targets: Array.isArray(options.targets) ? Object.assign({},
options.targets.indexOf('node') !== -1 ? { node: '8.9' } : {},
options.targets.indexOf('browsers') !== -1 ? { browsers: ['extends browserslist-config-google'] } : {}
) : options.targets,
}]);

// The two plugins above activate stage 3 features that babel hasn't added to the stage 3 preset yet
config.plugins.push(
// Allows class { handleClick = () => { } static propTypes = { foo: PropTypes.string } }
[require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }],
// Support destructuring of objects, e.g.: { ...foo }
[require.resolve('@babel/plugin-proposal-object-rest-spread'), { useBuiltIns: true }]
);

// Add react support
if (options.react) {
addReactSupport(config, options.env);
}

// Cherry-pick lodash modules for smaller bundles
if (options.lodash) {
addLodashSupport(config, options.lodash);
}

return config;
};
117 changes: 0 additions & 117 deletions index.js

This file was deleted.

Loading

0 comments on commit a5223bd

Please sign in to comment.