Node.js のビルドツール「esbuild」について!

記事
IT・テクノロジー

# はじめに


esbuild は、キャッシュなしで高速なビルドを可能とする Node.js のビルドツールです。

ビルドツールには、esbuild の他に、Webpack、Gulp、Parcel、Rollup、Browserify、FuseBox などがあります。

私自身が webpack を普段使っていて、ビルドに時間がかかりすぎているのが気になり、esbuild について調べてみようと思いました。

esbuild の特徴としては、

- キャッシュなしでの高速なビルド
- ES6 と CommonJS をサポート
- ES6 の Tree shaking 対応(利用されていないコードの除去)
- JavaScript と Go による API
- TypeScript と JSX をサポート
- ソースマップの生成
- ソースコードの最小化
- プラグイン(現在、experimental で v1.0.0 より前に対応予定)

が挙げられます。

この中でも注目すべきは、そのビルド速度にあると思います。

# なぜ早いのか?


1. esbuild は Go で書かれており、ネイティブコードへコンパイルしている

ほとんどのビルドツールは、Javascript によって書かれており、JIT コンパイルを使用するため、速度が遅い。

Go は、並列処理が得意で共有メモリをスレッド間で使用する。また、ヒープメモリも共有している。

よって、CPU を効率的に使用して、並列処理を行える。

2. 並列で処理を行う

昨今のPCは、複数のメモリを持っているため、効率的に並列処理を行える。

3. esbuild は、0 から速度を意識して作られた

3rd パーティライブラリを使用するのに比べ、パフォーマンスに対して多くのメリットが得られる。

例えば、多くのバンドラでは、公式の TypeScript コンパイラを使ってパースしているが、そのコンパイラは、パフォーマンスを最優先として作られていない。

その点、0 からパフォーマンスを最優先として作ることで、高速にコンパイルが可能となる。

4. メモリを効率的に使用する

esbuild は、JavaScript の抽象構文ツリーへは 3 回しかアクセスしない。

また、Go は、コンパクトにしてメモリに保存するため、より効率的にメモリを使用できる。

# esbuild の制限


- TypeScript の型チェックは行われない
- 別途 tsc を noEmit で実行し、チェックする必要があります
- ソースコードの変更監視が行われない
- sane などの watch ツールを利用すると良い
- CSS モジュール非対応
- 将来的に対応予定(ttps://github.com/evanw/esbuild/issues/20)
- CSS のバンドルに PostCSS + postcss-import を利用すると良い
- コード分割
- 将来的に対応予定(ttps://github.com/evanw/esbuild/issues/16)
- ES5へのトランスコンパイルができない
- 将来的に対応予定(ttps://github.com/evanw/esbuild/issues/297)

# 簡単な使い方


```
$ echo "{}" > package.json
$ yarn add esbuild react react-dom
```

```javascript:app.jsx
import * as React from 'react'
import * as Server from 'react-dom/server'

let Greet = () => <h1>Hello, world!</h1>
console.log(Server.renderToString(<Greet />))
```

```
$ ./node_modules/.bin/esbuild app.jsx --bundle --outfile=out.js
$ node out.js
```

# 速度比較


今回は、create-react-app で作ったアプリケーションのビルド速度を比較します。

## 通常の React アプリケーション

```
$ npx create-react-app react-ts-app --template typescript
$ cd react-ts-app
$ vim tsconfig.json
target を es2016 に修正
$ vim src/App.tsx
svg 関連のコードをコメントアウト
$ sudo rm -fr build && /usr/bin/time yarn build
```

## esbuild 版 React アプリケーション

```
$ npx create-react-app react-ts-app --template typescript
$ cd react-ts-app
$ vim tsconfig.json
target を es2016 に修正
$ vim src/App.tsx
svg 関連のコードをコメントアウト
```

```typescript:build.ts
const { argv } = require('process')
const { build } = require('esbuild')
const path = require('path')

const options = {
define: { 'process.env.NODE_ENV': process.env.NODE_ENV },
entryPoints: [path.resolve(__dirname, 'src/index.tsx')],
minify: argv[2] === 'production',
bundle: true,
target: 'es2016',
platform: 'browser',
outdir: path.resolve(__dirname, 'dist'),
tsconfig: path.resolve(__dirname, 'tsconfig.json')
}

build(options).catch(err => {
process.stderr.write(err.stderr)
process.exit(1)
})
```

```
$ sudo rm -fr build && /usr/bin/time node build.ts
```

## 結果

```
通常の React アプリケーション
3.91 real 5.40 user 0.66 sys
3.43 real 5.53 user 0.60 sys
2.96 real 5.25 user 0.57 sys

esbuild 版 React アプリケーション
0.10 real 0.12 user 0.02 sys
0.08 real 0.12 user 0.01 sys
0.08 real 0.12 user 0.01 sys
```

# おわりに


結果を見てもらうと分かるようにかなり高速にビルド出来ました。

create-react-app で作られるアプリケーションには、svg をインポートしている部分がありますが、ここは別途プラグインでやる必要がありそうですが、

今回の目的とは違っていたので、コメントアウトで対応しました。

単純に置き換えるだけではうまくいかないところがあったり、まだ、メジャーバージョンも 1 になっていなかったりするので、様子見しつつ、タイミングを見て導入できればと思います。

開発当初は気にならないほどの速度でビルド出来ていても、開発が進むにつれてだんだんビルドが遅くなり、ストレスに感じることもあるかと思います。

そんな時にぜひ esbuild も検討してみてはいかがでしょうか?

# お知らせ

Webサイト・ツール・LP作成のご依頼は、



こちらからお問い合わせいただけます。お気軽にご相談ください。

# 参考


ttps://github.com/evanw/esbuild

ttps://www.kabuku.co.jp/developers/ultrafast-tsx-build-tool-esbuild

サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す