JA Deployment Build Process - aku11i/phantom GitHub Wiki
ビルドプロセス
English | 日本語
このドキュメントでは、配布用のPhantomをビルドする方法とビルドシステムのアーキテクチャについて説明します。
ビルド概要
Phantomは、高速で効率的なビルドのためにesbuildを使用したカスタムTypeScriptビルドスクリプトを使用します。
ビルドスタック
- ビルドツール: esbuild(非常に高速なJavaScriptバンドラー)
- 言語: TypeScript
- ターゲット: Node.js v22+
- モジュール形式: ESモジュール(ESM)
- 出力: 自己完結型実行可能ファイル
ビルドスクリプト
ソース: build.ts
ビルドプロセスはTypeScriptファイルで定義されています:
import { build } from "esbuild";
import { chmod, mkdir } from "node:fs/promises";
import { dirname } from "node:path";
async function main() {
const entryPoint = "src/bin/phantom.ts";
const outfile = "dist/phantom.js";
// 出力ディレクトリが存在することを確認
await mkdir(dirname(outfile), { recursive: true });
// esbuildでビルド
await build({
entryPoints: [entryPoint],
outfile,
bundle: true,
platform: "node",
target: "node22",
format: "esm",
sourcemap: true,
minify: false,
banner: {
js: "#!/usr/bin/env node",
},
});
// 実行可能にする
await chmod(outfile, 0o755);
}
ビルド設定
esbuildオプション
オプション | 値 | 目的 |
---|---|---|
bundle |
true |
すべての依存関係を単一ファイルにバンドル |
platform |
"node" |
Node.js環境をターゲット |
target |
"node22" |
Node.js v22の機能を使用 |
format |
"esm" |
ESモジュールを出力 |
sourcemap |
true |
デバッグ用のソースマップを生成 |
minify |
false |
コードを読みやすく保つ |
banner |
#!/usr/bin/env node |
ファイルを実行可能にする |
出力構造
dist/
├── phantom.js # メイン実行可能ファイル(バンドル済み)
└── phantom.js.map # デバッグ用ソースマップ
ビルドの実行
基本的なビルド
# ビルドを実行
pnpm build
# または直接実行
npx tsx build.ts
ビルド出力
$ pnpm build
Building Phantom...
✓ Built dist/phantom.js (150KB)
✓ Made executable
Build completed in 0.2s
ビルドプロセスの詳細
1. 依存関係の解決
esbuildは自動的に:
- すべてのインポートを解決
- TypeScriptファイルをバンドル
- node_modulesを処理(開発時のみ)
- package.jsonのexportsを尊重
2. TypeScriptコンパイル
- TypeScriptはesbuildによってコンパイル
- 個別のtscステップは不要
- 型チェックは別途実行
- 高速な増分ビルド
3. モジュールバンドリング
入力: 出力:
src/ dist/phantom.js
├── bin/phantom.ts → (単一のバンドルファイル)
├── cli/handlers/*
├── core/worktree/*
└── core/git/*
4. 実行可能ファイルの作成
ビルドスクリプトは:
- シェバン(
#!/usr/bin/env node
)を追加 - 実行権限を設定(
chmod 755
) - すぐに実行できるCLIツールを作成
ビルドの最適化
なぜミニファイしないのか?
minify: false // 以下の理由で読みやすく保つ:
- デバッグ - スタックトレースが有用なまま
- サイズ - すでに小さい(~150KB)
- パフォーマンス - ランタイムの違いは無視できる
- セキュリティ - 隠すべき機密コードなし
バンドルサイズ分析
何が含まれているかを確認:
# バンドルを分析
npx esbuild src/bin/phantom.ts --bundle --analyze
# 出力に表示される内容:
# - ファイルサイズ
# - 含まれるモジュール
# - ツリーシェイキングの結果
開発ビルド vs 本番ビルド
開発ビルド
現在のビルド設定は開発用に最適化されています:
{
sourcemap: true, // デバッグサポート
minify: false, // 読みやすい出力
}
本番ビルド(必要な場合)
本番最適化の場合:
{
sourcemap: false, // より小さいサイズ
minify: true, // 圧縮された出力
treeShaking: true, // デッドコードを削除
}
ビルド統合
package.jsonスクリプト
ソース: package.json#L13-L14
{
"scripts": {
"build": "tsx build.ts",
"prepublishOnly": "pnpm run build"
}
}
自動ビルド
- 公開時:
prepublishOnly
がビルドを実行 - CI/CD: GitHub Actionsでビルドが実行
- ローカル開発: 手動で
pnpm build
クロスプラットフォームの考慮事項
ファイルパス
ビルドはパスを正しく処理します:
// Node.jsのpathモジュールを使用
import { dirname, join } from "node:path";
// ハードコードされたパスではない
const outfile = join("dist", "phantom.js");
改行コード
- ビルドはLF改行を出力
- Git設定により一貫性を確保
- Windows、macOS、Linuxで動作
実行権限
// Unix形式の権限
await chmod(outfile, 0o755);
// 以下と同等: -rwxr-xr-x
// 所有者: 読み取り、書き込み、実行
// グループ: 読み取り、実行
// その他: 読み取り、実行
ビルド成果物
含まれるもの
ビルドには以下が含まれます:
src/
からのすべてのソースコード- 型定義(コンパイル時に除去)
- ランタイム依存関係なし
- 開発依存関係なし
除外されるもの
バンドルされないもの:
- テストファイル(
*.test.ts
) - 開発依存関係
- TypeScriptソースファイル
- ドキュメント
ビルドパフォーマンス
メトリクス
典型的なビルド時間:
- フルビルド: ~200ms
- 増分: ~50ms
- ウォッチモード: 即座
なぜesbuildか?
他のバンドラーとの比較:
ツール | ビルド時間 | 機能 |
---|---|---|
esbuild | 0.2秒 | 高速、シンプル |
Webpack | 3-5秒 | 複雑、プラグイン |
Rollup | 2-3秒 | ツリーシェイキング |
tsc | 1-2秒 | 型チェックのみ |
ビルドのトラブルシューティング
よくある問題
1. ビルドが失敗する
# Nodeバージョンを確認
node --version # v22+である必要があります
# クリアして再ビルド
rm -rf dist
pnpm build
2. インポートエラー
// ✓ 正しい - 拡張子付き
import { something } from "./module.js";
// ✗ 間違い - 拡張子なし
import { something } from "./module";
3. モジュールが見つからない
# 依存関係がインストールされていることを確認
pnpm install
# インポートパスを確認
# 相対パスまたはnode_modulesからである必要があります
ビルドの問題をデバッグ
# 詳細なesbuild出力
npx esbuild src/bin/phantom.ts \
--bundle \
--platform=node \
--log-level=debug
# バンドルされた出力を確認
cat dist/phantom.js | less
カスタムビルドタスク
ビルド前のステップを追加
// build.ts内
async function prebuild() {
// distディレクトリをクリーン
await rm("dist", { recursive: true, force: true });
// バージョン情報を生成
await generateVersion();
}
async function main() {
await prebuild();
await build({ /* ... */ });
}
ビルド後のステップ
async function postbuild() {
// 追加ファイルをコピー
await copyFile("LICENSE", "dist/LICENSE");
// メタデータを生成
await writeFile("dist/metadata.json", JSON.stringify({
version,
buildTime: new Date().toISOString(),
}));
}
CI/CDビルドプロセス
GitHub Actionsビルド
CIパイプラインは以下を実行:
- name: Build
run: pnpm build
- name: Verify build
run: |
test -f dist/phantom.js
test -x dist/phantom.js
リリースビルド
npmリリース用:
# バージョンバンプ
npm version patch
# ビルドして公開
npm publish
# prepublishOnlyが自動的にビルドを実行
ビルドのベストプラクティス
1. ビルドを高速に保つ
- 速度のためにesbuildを使用
- 不要な変換を避ける
- 可能な場合はキャッシュ
2. 再現可能なビルド
- 依存関係をロック(
pnpm-lock.yaml
) - 正確なNodeバージョンを指定
- 一貫した環境を使用
3. ビルドの検証
常にビルドを検証:
# ビルドされた実行可能ファイルをテスト
./dist/phantom.js --version
./dist/phantom.js list
# ファイルサイズを確認
ls -lh dist/phantom.js
4. ソースマップ
開発に含める:
- デバッグサポート
- エラースタックトレース
- パフォーマンスプロファイリング
高度なビルドトピック
カスタムesbuildプラグイン
// 例: ビルド情報を追加
const buildInfoPlugin = {
name: "build-info",
setup(build) {
build.onResolve({ filter: /^BUILD_INFO$/ }, () => ({
path: "BUILD_INFO",
namespace: "build-info",
}));
build.onLoad({ filter: /.*/, namespace: "build-info" }, () => ({
contents: JSON.stringify({
version: process.env.npm_package_version,
buildTime: new Date().toISOString(),
}),
loader: "json",
}));
},
};
// ビルドで使用
await build({
plugins: [buildInfoPlugin],
// ... その他のオプション
});
ウォッチモード
開発用:
// build.tsに追加
if (process.argv.includes("--watch")) {
const ctx = await context({
// ... ビルドオプション
});
await ctx.watch();
console.log("変更を監視中...");
}
まとめ
Phantomのビルドプロセスは:
- 高速 - esbuildによるサブ秒ビルド
- シンプル - 単一のTypeScriptファイル設定
- 信頼性 - 一貫した、再現可能な出力
- 効率的 - 小さく、自己完結型の実行可能ファイル
- 開発者フレンドリー - ソースマップと読みやすい出力
ビルドシステムは、効率的で配布可能なCLIツールを生成しながら、開発者体験を優先します。