やしログ

ビルドツール素振り(esbuild編)

created: 2021/05/03
esbuild を素振りしてみました。

esbuild を使ったビルド設定をやってみる

ヌケニンフォルダ をベースに始めます。(詳しくは こちらの記事 を参照ください。)

まず esbuild をインストールします。

$ yarn add -D esbuild

次に、 package.json 内の script を以下のように書きかえます。

"scripts": {
     "start": "echo start",
-    "build": "echo build",
+    "build": "esbuild src/index.tsx --bundle --loader:.ts=ts --loader:.svg=dataurl --outfile=public/bundle.js --define:process.env.NODE_ENV=\\\"production\\\" --minify --sourcemap=external",
     "test": "echo test"
   },

これで一応ビルドはできるのですが、公式の推奨 通り、ビルドスクリプトを作ってみます。

import esbuild from 'esbuild';

esbuild
  .build({
    entryPoints: ['src/index.tsx'],
    bundle: true,
    loader: {
      '.ts': 'ts',
      '.svg': 'dataurl',
    },
    outfile: 'public/bundle.js',
    define: {
      'process.env.NODE_ENV': '"production"',
    },
    minify: true,
    sourcemap: 'external',
  })
  .catch(() => process.exit(1));

package.json は以下のようになります。良さそう。

"scripts": {
     "start": "echo start",
-    "build": "esbuild src/index.tsx --bundle --loader:.ts=ts --loader:.svg=dataurl --outfile=public/bundle.js --define:process.env.NODE_ENV=\\\"production\\\" --minify --sourcemap=external",
+    "build": "node build.mjs",
     "test": "echo test"
   },

esbuild を使った開発環境用のビルド設定をやってみる

続いて開発環境用の設定をやってみます。

まず、development/production の切り替えができるようにします。

 import esbuild from "esbuild";

- esbuild.build({
+ const buildOption = {
    entryPoints: ["src/index.tsx"],
    bundle: true,
    loader: {
@@ -13,4 +13,8 @@ esbuild.build({
    },
    minify: true,
    sourcemap: "external",
- }).catch(() => process.exit(1));
+ }
+
+ if (process.env.NODE_ENV === 'production') {
+   esbuild.build(buildOption).catch(() => process.exit(1));
+ }
   "scripts": {
     "start": "echo start",
-    "build": "node build.mjs",
+    "build": "NODE_ENV=production node build.mjs",
     "test": "echo test"
   },

esbuild は HMR をサポートしておらず、サポートする予定も無いようでした。

サポートされているオプションについてまとめると、以下のようでした。

  • ファイルの変更を監視し、変更されたらビルドする → watch オプションで可能
  • html などのサーブを行い、リクエスト時にビルドする → serve オプションで可能

今回やりたいこととしては「ファイル変更時にリビルドする & html をサーブする」だったのですが、 watchserve オプションを併用しようとすると UnhandledPromiseRejectionWarning: Error: Cannot use "watch" with "serve" といったエラーになりできませんでした。

とりあえず今回は、 serve だけ行えるようにしました。

if (process.env.NODE_ENV === 'production') {
  esbuild.build(buildOption).catch(() => process.exit(1));
}
+ else if (process.env.NODE_ENV === 'development') {
+   esbuild.serve({
+     servedir: 'public'
+   }, buildOption).then(serveResult => {
+     console.log(`http://${serveResult.host}/${serveResult.port}`)
+   }).catch(() => process.exit(1));
+ }
"scripts": {
-   "start": "echo start",
+   "start": "NODE_ENV=development node build.mjs",
    "build": "NODE_ENV=production node build.mjs",
    "test": "echo test"
  },

まとめ

esbuild は速度を最重要視し、機能を絞る(広げすぎない)方針を取っているようです。しかしこの裏返しで、 esbuild 単体でビルドを行おうとすると機能が足りていない面がまだ多いと感じました。(ビルド設定には影響しないのですが、下記のリンクにある通り、 css のサポートも現在(2021/05) WIP です。)

ここまでの結果は下記に置いています。

引き続き、他のビルドツールの記事も書いていきます!