esbuildのMake環境

これは下の話の続きです。

背景と動機の説明

esbuildを使い方をネットでいろいろ検索していくと、次のようなbuild.jsを書いて、buildするという話ばっかり見つかります。

import { build, BuildOptions } from 'esbuild';

// 変数などをセット(その部分は割愛)

build({
  entryPoints: ['src/index.tsx'],
  // 以下オプションが続くけど、省略
}).catch(() => process.exit(1))

しかし、これがうまく動作しません。1行目からエラーになってしまいます。原因は、esbuildをローカルではなくグローバルにinstallしてしまったことのようです。回避方法などの見当が全くつきません。

さらに私には、"npm run build"のようなビルド環境よりも、昔から使っているMakefileを使ったビルド環境の方がわかりやすいです。esbuildは普通にコマンドとして使うことができ、コマンドラインオプションでいろいろと制御できます。wsl環境ならmakeも使うことができますし、いろいろ細かい制御も行いやすいです。

そこで、最近はMakefileを準備して作業をしています。それの話をしたいと思います。

前提条件

前提条件やディレクトリ構成などを記載します。

  • コードのエディタはVisualStrudioCode(vscode)を使用。
  • wslを使用できるようになっており、vscodeのターミナルもwslに設定。wslで使っているUNIXはdebianにしています。
  • tsconfig.jsonを準備する。vscodeでエラーチェックさせたり、importを自動的に行わせるために使います。https://witch.mydns.jp/wp/preact20240329/で例を載せたものをそのまま使用。
  • esbuildはグローバルにインストール。
  • sasscをインストール済み。これは、scssファイルをcssファイルに変換するツールです。debianではaptitudeなどで簡単にインストールできます。
  • typed-css-modulesをグローバルにインストール済み。

typed-css-modules

typed-css-modulesは、CSS.moduleをTypeScriptで使う時にvscodeでエラーが出ないようにするためのファイルを作成するツールです。

npm install -g typed-css-modules

でグローバルインストールされ、以下のコマンドで使用できます。

tcm CSS.moduleの存在するディレクトリ

ディレトクリ構成

ソースファイルなどのディレクトリ構成は次のようになっています。

--+                  TOP環境
  +-Makefile         Makeファイル
  +-index.html       HTML
  +-index.js         src/以下のTypeScriptソースから作成
  +-main.scss        SCSSファイル
  +-main.css         main.scssから作成
  +-tsconfig.json    vscodeでエラーチェックや自動importのために用意する
  +-src/-+-          TypeScriptのソースを置くディレクトリ     
         +-styles/-  CSS.modulesを置くディレクトリ  

Makefile

実際に使用しているMakefileを下に示します。

ESOPTION := \
	--bundle \
	--charset=utf8 \
	--platform=browser \
	--target=ES2020 \
	--tree-shaking=true \

JS_LIST := index.js
SCSS_LIST := $(wildcard *.scss)
CSS_LIST := $(SCSS_LIST:.scss=.css) $(JS_LIST:.js=.css)
TS_LIST := $(wildcard src/*.ts) $(wildcard src/*.tsx)
IMPORT_CSS_FILES = $(wildcard src/styles/*.css)

RELEASE_DIR := Release
RELEASE_FILES := $(wildcard *.html) $(JS_LIST) $(CSS_LIST)

.PHONY: debug
debug: ESOPTION += --sourcemap=inline
debug: $(JS_LIST) $(CSS_LIST)

.PHONY: release
release: ESOPTION += --minify
release: $(JS_LIST) $(CSS_LIST)

%.js: src/%.ts $(TS_LIST) $(IMPORT_CSS_FILES)
	esbuild $(ESOPTION) --outdir=. $<
	nkf -w8 -Lw $@ > tmp; mv tmp $@
	if [ -f $(@:.js=.css) ]; then \
		(nkf -w8 -Lw $(@:.js=.css) > tmp ; mv tmp $(@:.js=.css) ); \
	fi

%.css: %.scss
	sassc -t expanded $< | nkf -w8 -Lw > $@

.PHONY: release_pack
release_pack:
	mkdir $(RELEASE_DIR)
	for file in $(RELEASE_FILES); \
	do cp $$file $(RELEASE_DIR)/$$file; \
	done

.PHONY: clean
clean:
	rm -rf $(JS_LIST) $(CSS_LIST) $(RELEASE_DIR)

.PHONY: tcm
tcm:
	tcm src/styles

説明

各行の説明は次の通りです。

1~6行目は、変数ESOPTIONをセットしています。これはesbuildのコマンドラインオプションです。それぞれの意味は次の通り。

--bundleTypeScriptをトランスパイルして、バンドルする指定。
--charset=utf8文字コードをUTF8にする指定。
--platform=browserブラウザ用にバンドルする指定。
--target=ES20202020年以降のブラウザに対応するようにトランスパイするする指定。
--tree-shaking=true無駄なコードを削除する指定。

8行目は作成するJSファイル名を変数JS_LISTにセットしています。例では1ファイルしかありませんが、複数指定してもよいです。

9行目はSCSSファイル名を変数SCSS_LISTにセットしています。ワイルドカードで指定しているので、トップディレクトリにあるすべてのSCSSファイルがセットされます。

10行目はCSSファイル名をCSS_LISTにセットしています。ここではSCSSファイルを変換して作成されるCSSファイル名と、esbuildによってCSS.moduleから作成されるCSSファイル名をせっとしています。

11行目はTypeScriptの全ソースファイルを変数TS_LISTにセットしています。この例ではソースがsrc/直下にのみ置かれることを想定していますが、ソースが増えてサブディレクトリを作るようになったなら、下のように変更します。

TS_LIST := $(wildcard src/*.ts) $(wildcard src/*.tsx) $(wildcard src/*/*.ts) $(wildcard src/*/*.tsx)

12行目は、CSS.moduleのCSSファイルをIMPORT_CSS_FILES変数にセットしています。

14行目は、リリースファイル(サーバー上に置くファイル)をまとめるためのディレクトリ名を変数RELEASE_DIRにセットしています。

15行目は、リリースファイル名のリストを変数RELEASE_FILESにセットしています。

途中を飛ばして、25~30行目は、esbuildを使ってindex.jsとindex.cssを作成するように指定しています。TypeScriptとCSS.moduleに変化があったときのみesbuildを実行します。また、nkfを使って文字コードを変えています。

(巻き戻って)17~19行目は、デバッグ版をトランスパイルするための設定を追加しています。ESOPTIONに --sourcemap=inline を追加することで、トランスパイスされたJSファイル中にsorucemapが追加されるようになり、TypeScriptソースを使ってデバッグ可能になります。

21~23行目は、リリース版をトランスパイルするための設定を追加しています。ESOPTIONに --minify を追加することで、トランスパイルされるJSファイルやCSSファイルが最小化されます。また、この設定により、make releaseでリリース版を作ることができます。

32~33行目は、sasscを使ってSCSSファイルからCSSファイルを生成するように指定しています。SCSSファイルが変化したときのみsasscを実行します。また、nkfを使って文字コードを変えています。

35~40行目は、リリースディレクトリを作って、リリースファイルをコピーします。これは、リリース作業のミスを減らすために、リリースするものだけを1か所に集めるための設定です。
make release_pack で作業を行うことができます。別になくてもよいのですが、間違って余計なファイルをリリースすることがないように、Makeで管理しています。

42~44行目は、トランパイルなどで生成されたファイルやリリースディレクトリなどをまとめて削除する設定です。make cleanで削除することができます。誤って必要なファイルを削除しないために、Makeで管理したほうが良いです。

46~48は、tcmを使って、CSS.moduleからvscode用のファイルを生成します。これも別になくてもよいのですが、make tcm だけで動かせた方が楽なので設定しています。

makeの使い方

普段(ソースの開発中やデバッグ中)は、make だけでデバッグ版のJSファイルCSSファイルが作成されます。

CSS.moduleを新しく作ったり、既存を変えたりした場合は、make tcmを使います。CSS.moduleに変更を行うと、ソースの変更中でもvscodeで、余計なエラーが出始めるので、esbuildのトランスパイルとは連動させていません。

開発が終わり、リリースするときは、
 make cleanでいったんJSファイルを削除、
 make releaseでリリース版作成、
 make release_packでリリースファイルをまとめる、
という作業を行って、リリースしています。

コメント