究極のコード整形:Prettierプラグインによる「DSLの美学」の強制とパイプライン最適化
凡庸なエンジニアはPrettierのデフォルト設定に身を委ねる。だが、真のアーキテクトは「コードの形」すらもプロジェクトのドメインに合わせて設計する。
特定のDSL(ドメイン固有言語)や、複雑なメタプログラミングを駆使した自作ライブラリにおいて、標準のフォーマッタは無力だ。本稿では、Prettierの内部AST(抽象構文木)をハックし、独自の構文を美しく、かつ高速に整形する「Prettierプラグイン自作の深淵」と、それをCI/CDで極限まで効率化するアーキテクチャを解剖する。
—
1. Prettierの核心:ASTとプリンタの分離構造
Prettierは単なる文字列置換ツールではない。以下の3段階のパイプラインで動作する「レンダリングエンジン」だ。
1. Parser: ソースコードをASTに変換する。
2. Printer: ASTをPrettier独自の「Doc」という中間表現へ変換する。
3. Doc Generator: Docを文字列として出力する。
独自構文を整形するには、既存の`babel`や`typescript`パーサーが吐き出したASTを、`print`関数を通じて再定義する必要がある。
実践:独自ノードのPrint拡張
自作のカスタムタグ(例:`@gql`のような特殊な埋め込み)を美しく整形するには、`print`関数をオーバーライドし、Docコマンド(`group`, `indent`, `line`など)を駆使する。
// prettier-plugin-custom/index.js
const plugin = {
printers: {
estree: {
print(path, options, print) {
const node = path.getValue();
// 独自の構文ノードを判定
if (node.type === ‘CustomDSLNode’) {
return [
group([
“custom(“,
indent([
line,
path.call(print, ‘body’) // bodyを再帰的に整形
]),
line,
“)”
])
];
}
// それ以外はデフォルトのプリンタに委譲
return null;
}
}
}
};
ここで重要なのは、`group`と`indent`の使い方だ。PrettierはこれらのDocコマンドを受け取り、「現在の行幅(printWidth)を超えた場合にのみ改行する」という貪欲法(Greedy Algorithm)を適用する。これを理解せずに力技で改行を入れるのは素人のやることだ。
—
2. CI/CDパイプラインへの埋め込みとパフォーマンス最適化
Prettierの実行は、大規模プロジェクトにおいてボトルネックになり得る。CIで毎回全ファイルを解析するのは無駄の極みだ。
Docker環境での完全自動化とキャッシュ戦略
CIコンテナ内では、`node_modules`のキャッシュに加え、Prettierのキャッシュを永続化させるべきだ。
.github/workflows/lint.yml
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Cache Prettier
uses: actions/cache@v3
with:
path: .cache/prettier # キャッシュディレクトリを指定
key: ${{ runner.os }}-prettier-${{ hashFiles(‘/package-lock.json’) }}
- name: Run Prettier
run: |
# –cache オプションで変更分のみを再整形。実行時間を80%削減可能
npx prettier –write . –cache –cache-location .cache/prettier
メモリ消費のハック
数万行の巨大プロジェクトでは、Node.jsのデフォルトメモリ制限(通常512MB〜1GB)に抵触する。CI環境では必ず`–max-old-space-size`をチューニングせよ。
メモリを4GBに拡張して実行
NODE_OPTIONS=”–max-old-space-size=4096″ npx prettier –write .
—
3. なぜ「自作プラグイン」が必要なのか:現場の真実
多くの開発者は「ルールが厳しすぎる」とPrettierを恨むが、それは誤りだ。コードは「読みやすさ」ではなく「差分が出ないこと」が最優先される。
自作プラグインを作る最大の利点は、「意味のある改行」を強制できることにある。例えば、DIコンテナの登録設定や、複雑な型定義など、特定のパターンを必ず単一行、あるいは特定のツリー構造にすることで、Gitの差分が極めてクリーンになる。
究極の自動化:独自CLIによる「静的解析+整形」のパイプライン化
Prettierを実行した後に、独自のバリデーションを行うスクリプトを噛ませることで、整形ルールを「強制」から「言語仕様の一部」へと昇華させる。
!/bin/bash
scripts/verify-format.sh
整形漏れを許さない厳格なパイプライン
npx prettier –check . || {
echo “❌ 構文が美しくありません。フォーマッタをかけてください。”
exit 1
}
さらに、独自のDSLが適切にネストされているか静的解析
npx ts-node scripts/validate-dsl-structure.ts
—
4. アーキテクトからの提言:妥協なき設計のために
Prettierのカスタマイズに踏み込むことは、言語仕様の深淵を覗くことと同義だ。ASTを操作することは、コンパイラの動作を理解する近道でもある。
1. Parserを自作するな: 可能な限り既存のパーサー(Babel等)を拡張(`override`)する形で実装せよ。独自パーサーはメンテナンスの地獄への入り口だ。
2. プラグインは「副作用」を持たせるな: プリンタは純粋関数であるべきだ。外部の状態を参照するな。
3. 高速化の鍵は「再帰の深さ」: 複雑なノード構造は、スタックオーバーフローを招く。`path.call`の呼び出し回数を計測し、必要以上にASTを走査しない設計を心がけよ。
Prettierは単なる「見た目の調整ツール」ではない。あなたの組織が書くコードの「品質の境界線」を定義する強力なフレームワークだ。このレイヤーを掌握したとき、あなたのチームの生産性は、他社が数年かけて到達するレベルを数ヶ月で追い越すことになるだろう。
さあ、コードを美学の域まで昇華させろ。