もう迷わない!PrettierのBracket Line設定完全ガイド
Prettierは、コードを整形(フォーマット)するためのツールですが、その設定項目の一つに「Bracket Line」があります。これは、HTML、JSX、Vueなどのテンプレート言語における閉じタグ(>
)の位置に関する設定を指します。
具体的には、要素に属性が複数行にわたって記述されている場合に、その閉じタグの>
をどのように配置するかを制御します。
設定値と挙動
「Bracket Line」には、主に以下の2つの設定値があります。
-
true
(デフォルト): 閉じタグを最終属性と同じ行に配置するこれがPrettierのデフォルトの挙動です。属性が複数行にわたって記述されている場合でも、閉じタグの
>
は、最後の属性と同じ行に記述されます。例
<button className="my-button" onClick={() => doSomething()} disabled={false} > Click Me </button>
この例では、
disabled={false}
が最後の属性であり、その直後に閉じタグの>
が来ています。 -
false
: 閉じタグを最終属性とは別の行に配置するこの設定にすると、属性が複数行にわたって記述されている場合、閉じタグの
>
は、属性のインデントレベルを維持したまま、新しい行に配置されます。例
<button className="my-button" onClick={() => doSomething()} disabled={false} > Click Me </button>
この例では、
disabled={false}
の後に改行され、閉じタグの>
が新しい行に配置されています。
どちらを選ぶべきか?
これは完全に個人の好みやチームのコーディング規約に依存します。
- false の利点
- 閉じタグが常に一貫した位置(属性リストの直下の新しい行)に来るため、視覚的な一貫性が高まる。
- 属性の追加や削除がしやすくなる(最後の属性にカンマを追加する必要がない場合など)。
- true (デフォルト) の利点
- コードの行数が少なくなる傾向がある。
- 閉じタグが属性のすぐ後に来るため、視覚的に関連性が分かりやすいと感じる人もいる。
多くの場合、デフォルトのtrue
で問題ありませんが、コードの可読性を高めるためにfalse
に設定するチームもあります。
設定方法
package.json
のprettier
フィールドや、.prettierrc
ファイルなどで設定できます。
{
"printWidth": 80,
"tabWidth": 2,
"singleQuote": true,
"jsxBracketSameLine": false // これがBracket Lineの設定に相当
}
「Bracket Line」の設定自体は比較的単純ですが、他のPrettier設定、あるいはESLintのような他のフォーマッターやリンターとの組み合わせによって、意図しない挙動やエラーが発生することがあります。
設定が適用されない
最も一般的な問題は、「bracketSameLine: false
にしたのに、閉じタグが改行されない!」といった、設定が意図通りに適用されないケースです。
考えられる原因とトラブルシューティング
- 対象ファイルの種類
bracketSameLine
はHTML、JSX、Vueなどのテンプレート言語に適用されます。JavaScriptやTypeScriptの純粋なコードでは、このオプションは関係ありません。ファイルの種類が正しいか確認してください。- 特にVueファイルの場合、
.prettierrc
に"parser": "vue"
など、適切なパーサーが設定されているか確認してください。
- Prettierのバージョンが古い
bracketSameLine
オプションは比較的新しいPrettierのバージョンで導入された可能性があります。古いバージョンを使用している場合、期待通りに動作しないことがあります。最新のPrettierにアップデートしてみてください。- また、以前の
jsxBracketSameLine
オプションからbracketSameLine
に名称が変更されています。古いオプション名を使っている場合、正しく認識されないことがあります。
- 他のPrettierオプションとの競合
printWidth
(行の最大幅)などの他のオプションが、bracketSameLine
の意図した挙動を上書きしている可能性があります。例えば、printWidth
が非常に小さい値に設定されている場合、bracketSameLine: true
であっても、閉じタグが改行されることがあります。
- キャッシュの問題
- npm/yarnのキャッシュ、またはPrettier自身のキャッシュが原因で、古い設定が適用されている場合があります。
node_modules
を削除し、npm install
またはyarn install
を再実行してみてください。
- npm/yarnのキャッシュ、またはPrettier自身のキャッシュが原因で、古い設定が適用されている場合があります。
- Prettierの設定ファイルが正しく読み込まれていない
.prettierrc
やpackage.json
のprettier
フィールドなど、設定ファイルのパスや構文が正しいか確認してください。- VS Codeなどのエディタを使用している場合、Prettier拡張機能が正しく動作しているか確認してください(再起動や拡張機能の再インストールを試す)。
- プロジェクトのルートディレクトリに設定ファイルがあるか確認してください。
ESLintなど他のツールとの競合
PrettierとESLint(または他のリンターやフォーマッター)を併用している場合に、Formatterのルールが競合して、意図しないフォーマットになったり、エラーが発生したりすることがあります。
考えられる原因とトラブルシューティング
- エディタの「保存時にフォーマット」設定の競合
- VS Codeなどのエディタで、「保存時にフォーマット(Format On Save)」機能が有効になっている場合、PrettierとESLintの両方がフォーマットを試みて、結果が不安定になることがあります。
- 解決策
- エディタの設定で、デフォルトのフォーマッターをPrettierに設定し、ESLintのフォーマット機能を無効にするか、Prettierのフォーマットを優先するように設定します。
- VS Codeの場合:
// .vscode/settings.json の例 { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": "never" // ESLintの自動修正(フォーマット含む)を無効化 } }
source.fixAll.eslint
をnever
に設定することで、ESLintによるフォーマットの競合を回避できます。
- フォーマットルールの競合
- ESLintにも、
bracketSameLine
に似た括弧の配置に関するルールが存在する場合があります。PrettierとESLintの両方で同じスタイルのルールを設定していると、競合が発生します。 - 解決策
eslint-config-prettier
を使用して、ESLintのフォーマットに関するルールを無効にし、Prettierにフォーマットの責任を一本化することを強く推奨します。eslint-config-prettier
をインストールします。npm install --save-dev eslint-config-prettier # または yarn add --dev eslint-config-prettier
.eslintrc
ファイル(またはESLintの設定ファイル)のextends
配列の最後にprettier
を追加します。// .eslintrc.json の例 { "extends": [ "eslint:recommended", // 他のextends設定... "prettier" // **必ず最後に配置** ], // ... }
- ESLintにも、
特定の要素や状況で意図通りに動作しない
Prettierが常に完璧というわけではなく、特定の複雑なHTML構造やJSXのネストで、bracketSameLine
が期待通りに適用されないケースが報告されることがあります。
考えられる原因とトラブルシューティング
- ホワイトスペースの扱いの問題
- 特にHTMLやVueテンプレートでは、ホワイトスペースの扱いが厳密な場合があり、Prettierが意図しない改行やスペースを挿入・削除することがあります。これには
htmlWhitespaceSensitivity
オプションが関連する場合があります。- 例えば、
htmlWhitespaceSensitivity: "ignore"
に設定すると、HTML内のホワイトスペースをより柔軟に扱うようになりますが、これがbracketSameLine
の挙動に影響を与える可能性もゼロではありません。
- 例えば、
- 特にHTMLやVueテンプレートでは、ホワイトスペースの扱いが厳密な場合があり、Prettierが意図しない改行やスペースを挿入・削除することがあります。これには
- Prettierのバグや制約
- ごく稀に、特定のケースでPrettierのパーサーが正しく構造を認識できず、
bracketSameLine
のルールが適用されないバグが存在する場合があります。GitHubのPrettierリポジトリで同様のIssueが報告されていないか確認するか、自分でIssueを報告することを検討してください。
- ごく稀に、特定のケースでPrettierのパーサーが正しく構造を認識できず、
CI/CDパイプラインでのエラー
ローカルでは問題ないのに、CI/CDパイプラインでPrettierがエラーを吐くことがあります。
- EOL (End of Line) の問題
- WindowsとLinux/macOSで改行コード(CRLF vs LF)が異なるために、Prettierが異なる出力を生成し、
--check
でエラーになることがあります。 - 解決策
.prettierrc
でendOfLine: "lf"
を明示的に設定し、すべての環境でLF改行を使用するように統一します。また、Gitの設定でcore.autocrlf
を適切に設定することも重要です。
- WindowsとLinux/macOSで改行コード(CRLF vs LF)が異なるために、Prettierが異なる出力を生成し、
- --check フラグの使用
- CI/CDでは
prettier --check
を使用して、フォーマットされていないファイルがないかを検証することが一般的です。この際に、期待通りのフォーマットが適用されていないとエラーになります。
- CI/CDでは
- 環境の差異
- ローカルとCI/CD環境でPrettierのバージョンが異なる、または設定ファイルが正しくコピーされていない可能性があります。
このオプションは、.prettierrc
などの設定ファイルで bracketSameLine
として指定します。以前は JSX 専用の jsxBracketSameLine
というオプション名でしたが、より汎用的な bracketSameLine
に統一されました(古いバージョンではまだ jsxBracketSameLine
が使われることもあります)。
設定ファイル(例: .prettierrc
)
Prettier の設定は、通常プロジェクトのルートディレクトリに .prettierrc
というファイルを作成して行います。
bracketSameLine: true
の場合
閉じタグ >
が最後の属性と同じ行に配置されます。
// .prettierrc
{
"printWidth": 80,
"tabWidth": 2,
"singleQuote": true,
"bracketSameLine": true
}
bracketSameLine: false
の場合
閉じタグ >
が新しい行に配置されます。これは Prettier のデフォルトの挙動です。
// .prettierrc
{
"printWidth": 80,
"tabWidth": 2,
"singleQuote": true,
"bracketSameLine": false
}
コード例
以下の HTML/JSX のコードを Prettier でフォーマットした場合の比較を見ていきましょう。
元のコード(フォーマット前)
<button className="my-button" onClick={() => doSomething()} disabled={false}>
Click Me
</button>
<div
id="container"
data-testid="main-container"
aria-label="Example Container"
>
Some content inside.
</div>
<MyComponent
propA="valueA"
propB={123}
propC={true}
>
Child Content
</MyComponent>
bracketSameLine: true の場合
.prettierrc
で "bracketSameLine": true
と設定し、上記のコードを Prettier でフォーマットすると、以下のようになります。
フォーマット後のコード
<button
className="my-button"
onClick={() => doSomething()}
disabled={false}>
Click Me
</button>
<div
id="container"
data-testid="main-container"
aria-label="Example Container">
Some content inside.
</div>
<MyComponent
propA="valueA"
propB={123}
propC={true}>
Child Content
</MyComponent>
解説
- 閉じタグの
>
は、最後の属性が記述されている行の末尾に配置されています。 - すべての要素(
button
、div
、MyComponent
)において、属性が複数行にわたって記述されています。
bracketSameLine: false の場合(デフォルト)
.prettierrc
で "bracketSameLine": false
と設定するか、bracketSameLine
オプションを全く指定しない(デフォルト値が false
のため)で、上記のコードを Prettier でフォーマットすると、以下のようになります。
フォーマット後のコード
<button
className="my-button"
onClick={() => doSomething()}
disabled={false}
>
Click Me
</button>
<div
id="container"
data-testid="main-container"
aria-label="Example Container"
>
Some content inside.
</div>
<MyComponent
propA="valueA"
propB={123}
propC={true}
>
Child Content
</MyComponent>
解説
- 閉じタグの
>
は、新しい行に配置され、開始タグと同じインデントレベルになっています。 - すべての要素において、属性が複数行にわたって記述されています。
どちらのスタイルを選ぶべきか?
これは完全にチームや個人のコーディングスタイルに依存します。
bracketSameLine: false
は、閉じタグが常に独立した行に配置されるため、視覚的な一貫性が高く、属性の追加や削除が容易になるという利点があります。特に、属性のリストが長くなる場合に、変更差分(diff)が見やすくなるという意見もあります。bracketSameLine: true
は、コードの行数を少し減らし、閉じタグが属性と視覚的に近くにあるため、コンパクトに見えるという利点があります。
Prettierの「Bracket Line」(bracketSameLine
オプション)は、閉じタグ>
の位置を制御するためのオプションです。Prettierは「意見が強い(Opinionated)」フォーマッターであり、開発者間のスタイルに関する議論をなくすことを目的としているため、カスタマイズできるオプションは比較的少ないです。
そのため、「Bracket Line」に関してPrettier内でこのオプションの代替となるような「別のプログラミング方法」というものは基本的に存在しません。Prettierが提供するbracketSameLine
オプションを使用するか、使用しないか、のどちらかになります。
しかし、もし「PrettierのbracketSameLine
オプションの挙動では満足できない」という状況であれば、以下のような「代替手段」を検討することになります。
Prettierの他のオプションとの組み合わせ
bracketSameLine
オプションの挙動は、printWidth
(行の最大幅)などの他のPrettierオプションによって影響を受けることがあります。
- printWidth を調整する
printWidth
が非常に小さい値に設定されている場合、bracketSameLine: true
であっても、Prettierがその行の幅を超えないようにするために、閉じタグを強制的に改行させることがあります。- 逆に、
printWidth
を大きく設定すれば、bracketSameLine: true
の場合に閉じタグが改行されにくくなるかもしれません。 - ただし、これは直接的な代替ではなく、
printWidth
はコード全体の整形に影響を与えるため、他の部分のフォーマットも変わってしまう点に注意が必要です。
Prettierの// prettier-ignoreコメントを使用する
特定のコードブロックや行に対してのみ、Prettierのフォーマットを無効にすることができます。
- // prettier-ignore
-
このコメントを特定のHTML/JSX要素の直前に記述することで、その要素のフォーマットをPrettierの対象外にできます。
-
これにより、閉じタグの配置をPrettierに任せず、手動で制御することが可能になります。
-
<MyComponent propA="valueA" propB={123} propC={true} > {/* 閉じタグを意図的にここに配置 */} Child Content </MyComponent>
-
注意点
これは「Prettierを使わない」という選択肢であり、チームで統一されたフォーマットを維持するというPrettierの目的とは反します。どうしても特定の箇所だけ手動で制御したい場合にのみ使うべきです。
-
Prettierの「Bracket Line」の挙動がどうしても合わない場合、Prettier以外のツールを検討することになります。
- よりカスタマイズ性の高いフォーマッター
- Prettierはカスタマイズ性が低いことで知られています。もし「Bracket Line」だけでなく、他の多くのフォーマットオプションも細かく制御したいのであれば、よりカスタマイズ可能な他のフォーマッターを検討する手もあります。
- 例としては、特定のIDEに組み込まれたフォーマッター(VS CodeのJavaScript/TypeScript標準フォーマッターなど)や、言語に特化した独自のフォーマッターなどが挙げられます。しかし、これらのツールはPrettierほど普及しておらず、プロジェクト内で統一されたフォーマットを維持するのが難しくなる可能性があります。
- 「dprint」のような、より設定が豊富なフォーマッターも存在します。
- ESLint
- ESLintは主にコードの品質チェック(リンティング)を行うツールですが、一部のルールはフォーマットに関わるものもあります。
- 例えば、ESLintには
brace-style
のような波括弧の配置に関するルールがありますが、閉じタグ>
に直接的に影響するようなルールはPrettierほど強力ではありません。 - しかし、ESLintとPrettierを併用する際に、
eslint-plugin-react
やeslint-plugin-vue
といったプラグインのルールが、間接的に閉じタグの位置に影響を与える可能性はゼロではありません。 - トラブルシューティングの項目で説明したように、通常は
eslint-config-prettier
を使用して、ESLintのフォーマットルールをPrettierと競合しないように設定します。 もしPrettierのbracketSameLine
の挙動に満足できないのであれば、ESLint側でより詳細なルールを設定し、Prettierの一部フォーマットをESLintに任せるという道も考えられます。しかし、これはESLintとPrettierの役割分担を複雑にするため、推奨されません。
Prettierの「Bracket Line」オプション(bracketSameLine
)に対する「代替プログラミング方法」は、Prettierの設計思想上、直接的なものはほとんどありません。基本的にはこのオプションを使うか使わないか、または// prettier-ignore
で特定のコードブロックを無視するか、という選択になります。
もし、Prettierのこの挙動がプロジェクトの要求にどうしても合わないのであれば、それはPrettierが提供する「意見(opinion)」とは異なるフォーマットを求めているということになります。その場合は、// prettier-ignore
を限定的に使用するか、最終手段としてPrettier以外のフォーマッターを検討する、という流れになります。