もうBabelじゃない - Bubleだ。

JavaScript を書くとき、もはや新しい ES でないとストレスではないでしょうか。

だからこそ僕らは新しい ES で開発してから、ブラウザ対応のために [Babel](https://www.npmjs.com/package/babel) を使って ES5 にトランスパイルするというのが定石となっていました。

しかし、必要最小限の機能に絞って高速なトランスパイルを実現する [**Buble**](https://www.npmjs.com/package/buble) [^1] が登場しました。

[^1]: 読み方はバブル？ブーブレ？誰か教えてください。

# TL;DR

**Buble** は、 Babel やその他のトランスパイラと比べて以下の点で異なります。
 
- 仕様への準拠ではなくブラウザで動くことを目指す
- 設定ファイルは不要
- 高速なトランスパイル

Babel は新しい ES で書かれたコードを ES5 ( など )の仕様に準拠したコードにトランスパイルすることが目的です。一方で、新しい ES から ES5 への “完全” な変換は不可能です。

そこで **Buble** の取ったアプローチは、他仕様へのトランスパイルではなく、**ブラウザで動くコード**へのトランスパイルです。

ES5 にトランスパイルするのは、結局のところブラウザで動かすためじゃないですか？

**Buble** のアプローチは理にかなっています。

# Buble を使用する

まずは npm からインストールします。

```
npm install --save-dev buble
```

ES2015 で書いたコードを用意します。

```js:input.js
const add = ( a, b ) => a + b;
```

単純なトランスパイルなら以下のコマンドでできます。

```
buble input.js > output.js
```

```js:output.js
var add = function ( a, b ) { return a + b; };
```

[**Buble** の公式ドキュメント](http://buble.surge.sh/)では、どのようなコードがどのようにトランスパイルされるのか試すことができます。

## ブラウザバージョンを指定

これがやりたかったことです。対応ブラウザとバージョンを指定してトランスパイルします。

指定できるブラウザとバージョンは [このソース](https://gitlab.com/Rich-Harris/buble/blob/master/src/support.js) を見ると分かります。

Chrome 50 を指定しました。

```
buble input.js --target chrome:50 > output.js
```

結果はこうです。

```js:output.js
const add = ( a, b ) => a + b;
```

Chrome 50 は ES2015 に対応しているので元のコードから何も変わっていません。

次は指定できるすべてのブラウザで、一般的に普及していそうなバージョンを指定してみます。

```
buble input.js --target chrome:49,node:4,firefox:45,safari:9,edge:12,ie:11 > output.js
```

```js:output.js
var add = function ( a, b ) { return a + b; };
```

昔ながらのコードに変わりました。

開発しているプロジェクトに合わせて `--target` に指定するブラウザを変えるだけで、**Buble** がその環境で動くコードにトランスパイルします。

# モジュールの import/export は Rollup

**Buble** は 意図的に `import` と `export` を非サポートとしています。

`import` / `export` を使う場合、同じ作者によるモジュールバンドラーである [Rollup](https://www.npmjs.com/package/rollup) の使用が推奨されています。

Rollup の使い方は [こちらのQiita( @cognitom )](http://qiita.com/cognitom/items/e3ac0da00241f427dad6) が分かりやすくてオススメです。

## Rollup で Buble を使う

Rollup プラグインをインストールします。このプラグインをインストールすれば依存関係の解決のために Buble もインストールされます。

```
npm install --save-dev rollup-plugin-buble
```

Rollup の設定ファイルで使えるようにします。

```js:rollup.config.js
import buble from 'rollup-plugin-buble'

export default {
	entry: 'src/main.js',
	dest: 'dist/bundle.js',
	plugins: [
		buble( {
			target : {
				chrome: 49,
				node: 4,
				firefox: 45,
				safari: 9,
				edge: 12,
				ie: 11
			}
		} )
	]
}
```

CLI から実行するときのオプションを、そのままオプションとして指定できます。

オプションは [公式ドキュメント](http://buble.surge.sh/guide/) にまとめられています。

# サポートしないもの

Buble は `import` / `export` の他にもサポートしていない仕様があります。

- タグ付けされたTemplate string
- for...of
- Iterator / Generator
- 正規表現の y フラグ
- 末尾呼出し最適化

これらは将来的にサポートされる可能性がありますが、現状では [core-js](https://www.npmjs.com/package/core-js) や [es6-shim](https://www.npmjs.com/package/es6-shim) などの Polyfill を使うことを推奨しています。

# 変換速度

申し訳ないことに真面目な計測はしていませんが、体感で明らかに Babel よりも早くなりました。1/2 ~ 1/3 くらいでしょうか。

Babel は AST( 抽象構文木 ) から中間フォーマットの AST を生成して、その AST からコードを生成するので時間がかかかります。

対して **Buble** では AST から中間フォーマットを介すことなく直接コードを生成しています。

そのため **Buble** は Babel のようにプラグインを併用することはできませんが、**Buble** はインストールすればそれだけで動作することを重要視 [^Can we have plugins] しています。トランスパイルのためだけに複雑な設定に気を取られたくありませんよね？それよりもシンプルな解決法と高速な動作を求めています。大抵はそのままの **Buble** で事足りるはずです。

[^Can we have plugins]: [FAQ](https://buble.surge.sh/guide/#faqs) より > Q:Can we have plugins? A:No. The whole point of Bublé is that it's quick to install and takes no mental effort to set up. Plugins would ruin that.

私はいま、現行のプロジェクトを Babel から **Buble** に移行して快適にビルドしています。