babel 7 触ってみたメモ

babel初学者が[Babel 7](https://babeljs.io/)を使ってみたメモ。
初babelなので認識違いなどあればご指摘ください。 (Qiitaも初めてなので文化的暗黙のルールとかもわかってないです
docs: https://babeljs.io/docs/

```json
node: "10.4.0"
@babel/cli: "7.1.5"
@babel/core: "7.1.6"
@babel/preset-env: "7.1.6"
@babel/polyfill: "7.0.0"
```

## install

```sh
$ yarn add --dev @babel/core @babel/cli @babel/preset-env
```
babel7からはパッケージ名が`@babel/xxx`に変更になっている。

## config
```sh
$ touch babel.config.js
```

`babel.config.js`

```js
const presets =  [
  ["@babel/preset-env"]
};
module.exports = { presets }
```
パッケージ名が変更になってるので、`"env"`とか`"preset-env"`とかを指定しているとエラーになる

### targets

[browserslist](https://github.com/browserslist/browserslist)は`target`プロパティに直接渡す。

`babel.config.js`

```js
const presets =  [
  ["@babel/preset-env", {
    "targets": [">0.25% in JP", "not ie <= 10", "not op_mini all"],
  }]
};
```

##### `targets.browsers`での指定は廃止予定

```js
const presets =  [
  ["@babel/preset-env", {
    "targets": {
      "browsers": [">0.25% in JP", "not ie <= 10", "not op_mini all"],
    },
  }]
};
```
babel 7 で動作するけど、`browsers`での指定は将来的に廃止予定っぽい

fc. https://babeljs.io/docs/en/babel-preset-env#targetsbrowsers
>Note: this will be removed in later version in favor of just setting "targets" to a query directly.

#### 動作チェク
`package.json`にバベるコマンドを作成

```json
"scripts": {
  "babel": "./node_modules/.bin/babel src --out-dir dist/js",
}
```

`src/index.js`

```js
import { foo, bar } from './test.js'
console.log( foo() );

const countup = (x) => x + 1;
console.log( countup(1) )

Promise.resolve().then(res => console.log("Promise end") );
```

**バベる**

```sh
$ yarn run babel
```

👇 `dist/js/index.js`

```js
var _test = require("./test.js");

console.log((0, _test.foo)());

var countup = function countup(x) {
  return x + 1;
};

console.log(countup(1));
Promise.resolve().then(function (res) {
  return console.log("Promise end");
});
```

## @babel/polyfill

https://babeljs.io/docs/en/babel-polyfill

`Promise`や`WeakMap`, `Array.from`, `Object.assign`, `Array.prototype.includes`など文法ではなく、機能を対応していないブラウザ用に変換する  
=> つまり、コードを直接変換する機能  

#### install

```sh
$ yarn add @babel/polyfill
```

#### Usage

`babel.config.js`に`useBuiltIns: "usage"`を指定すれば、必要に合わせてプラグインを選び変換してくれるっぽい

> Now luckily for us, we're using the `env` preset which has a `"useBuiltIns"` option that when set to `"usage"` will practically apply the last optimization mentioned above where you only include the polyfills you need. 

`babel.config.js`

```js
const presets =  [
  ["@babel/preset-env", {
    "targets": [">0.25% in JP", "not ie <= 10", "not op_mini all"],
    "useBuiltIns": "usage",
  }]
};
```

#### 動作チェク

```js
Promise.resolve().then(res => console.log("Promise end") );
```

👇 **バベる**

```js
require("core-js/modules/es6.promise");

Promise.resolve().then(function (res) {
  return console.log("Promise end");
});
```

`core-js/modules/es6.promise`が追加されている。

`async/await`

```js
const asyncSampleFunc = () => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 100, "resolve");
  });
}

async function getAsyncVal() {
  const val = await asyncSampleFunc();
  return `Complete Async: ${val}`
}

getAsyncVal().then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
});
```

👇 **バベる**

```js
require("regenerator-runtime/runtime");

require("core-js/modules/es6.promise");

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

var asyncSampleFunc = function asyncSampleFunc() {
  return new Promise(function (resolve, reject) {
    setTimeout(resolve, 100, "resolve");
  });
};

function getAsyncVal() {
  return _getAsyncVal.apply(this, arguments);
}

function _getAsyncVal() {
  _getAsyncVal = _asyncToGenerator(
  /*#__PURE__*/
  regeneratorRuntime.mark(function _callee() {
    var val;
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return asyncSampleFunc();

          case 2:
            val = _context.sent;
            return _context.abrupt("return", "Complete Async: ".concat(val));

          case 4:
          case "end":
            return _context.stop();
        }
      }
    }, _callee, this);
  }));
  return _getAsyncVal.apply(this, arguments);
}

getAsyncVal().then(function (res) {
  console.log(res);
}).catch(function (err) {
  console.log(err);
});
```

変換できたっぽい。 <small style="font-size:80%;">(以前`async/await`使ってるプロダクト作ってる人に`async/await`はバベれないって言われたのでダメなのかと思ってた...</small>


## import -> require　問題

デフォルトだと、`import`が`require`(CommonJS?)に変換されてしまう。 

`modules: false`を指定すると`import`のままになる  

`babel.config.js`

```js
const presets =  [
  ["@babel/preset-env", {
    "modules": false,
    "targets": [">0.25% in JP", "not ie <= 10", "not op_mini all"],
    "useBuiltIns": "usage",
  }]
};
```

#### 動作チェク

`src/index.js`

```js
import { foo, bar } from './test.js'
console.log( foo() );

const countup = (x) => x + 1;
console.log( countup(1) )

Promise.resolve().then(res => console.log("Promise end") );
```

👇 **バベる**

`dist/js/index.js`

```js
import "core-js/modules/es6.promise";
import { foo, bar } from './test.js';
console.log(foo());

var countup = function countup(x) {
  return x + 1;
};

console.log(countup(1));
Promise.resolve().then(function (res) {
  return console.log("Promise end");
});
```

`import`文のまましゅつりょくされた。

cf. https://babeljs.io/docs/en/babel-preset-env#modules

> **modules**
> `"amd"` | `"umd"` | `"systemjs"` | `"commonjs"` | `"cjs"` | `"auto"` | `false`, defaults to `"auto"`.
> Enable transformation of ES6 module syntax to another module type.
> Setting this to false will not transform modules.
> Also note that `cjs` is just an alias for `commonjs`.


---

## [WIP]
- `.babelrc`と`babel.config.js`の使い分けがイマイチわかってない。<br>https://babeljs.io/docs/en/configuration
- 時々見かける`loose`オプションが何をするのかイマイチわかっていない。<br>https://babeljs.io/docs/en/babel-preset-env#loose

英語ちからが足りていない...