もう迷わない!PrettierのBracket Line設定完全ガイド

2025-06-06

Prettierは、コードを整形(フォーマット)するためのツールですが、その設定項目の一つに「Bracket Line」があります。これは、HTML、JSX、Vueなどのテンプレート言語における閉じタグ(>)の位置に関する設定を指します。

具体的には、要素に属性が複数行にわたって記述されている場合に、その閉じタグの>をどのように配置するかを制御します。

設定値と挙動

「Bracket Line」には、主に以下の2つの設定値があります。

  1. true (デフォルト): 閉じタグを最終属性と同じ行に配置する

    これがPrettierのデフォルトの挙動です。属性が複数行にわたって記述されている場合でも、閉じタグの>は、最後の属性と同じ行に記述されます。


    <button
      className="my-button"
      onClick={() => doSomething()}
      disabled={false}
    >
      Click Me
    </button>
    

    この例では、disabled={false}が最後の属性であり、その直後に閉じタグの>が来ています。

  2. false: 閉じタグを最終属性とは別の行に配置する

    この設定にすると、属性が複数行にわたって記述されている場合、閉じタグの>は、属性のインデントレベルを維持したまま、新しい行に配置されます。


    <button
      className="my-button"
      onClick={() => doSomething()}
      disabled={false}
    >
      Click Me
    </button>
    

    この例では、disabled={false}の後に改行され、閉じタグの>が新しい行に配置されています。

どちらを選ぶべきか?

これは完全に個人の好みやチームのコーディング規約に依存します。

  • false の利点
    • 閉じタグが常に一貫した位置(属性リストの直下の新しい行)に来るため、視覚的な一貫性が高まる。
    • 属性の追加や削除がしやすくなる(最後の属性にカンマを追加する必要がない場合など)。
  • true (デフォルト) の利点
    • コードの行数が少なくなる傾向がある。
    • 閉じタグが属性のすぐ後に来るため、視覚的に関連性が分かりやすいと感じる人もいる。

多くの場合、デフォルトのtrueで問題ありませんが、コードの可読性を高めるためにfalseに設定するチームもあります。

設定方法

package.jsonprettierフィールドや、.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 を再実行してみてください。
  • Prettierの設定ファイルが正しく読み込まれていない
    • .prettierrcpackage.jsonprettier フィールドなど、設定ファイルのパスや構文が正しいか確認してください。
    • 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.eslintnever に設定することで、ESLintによるフォーマットの競合を回避できます。
  • フォーマットルールの競合
    • ESLintにも、bracketSameLine に似た括弧の配置に関するルールが存在する場合があります。PrettierとESLintの両方で同じスタイルのルールを設定していると、競合が発生します。
    • 解決策
      eslint-config-prettier を使用して、ESLintのフォーマットに関するルールを無効にし、Prettierにフォーマットの責任を一本化することを強く推奨します。
      1. eslint-config-prettier をインストールします。
        npm install --save-dev eslint-config-prettier
        # または
        yarn add --dev eslint-config-prettier
        
      2. .eslintrc ファイル(またはESLintの設定ファイル)の extends 配列の最後に prettier を追加します。
        // .eslintrc.json の例
        {
          "extends": [
            "eslint:recommended",
            // 他のextends設定...
            "prettier" // **必ず最後に配置**
          ],
          // ...
        }
        

特定の要素や状況で意図通りに動作しない

Prettierが常に完璧というわけではなく、特定の複雑なHTML構造やJSXのネストで、bracketSameLine が期待通りに適用されないケースが報告されることがあります。

考えられる原因とトラブルシューティング

  • ホワイトスペースの扱いの問題
    • 特にHTMLやVueテンプレートでは、ホワイトスペースの扱いが厳密な場合があり、Prettierが意図しない改行やスペースを挿入・削除することがあります。これには htmlWhitespaceSensitivity オプションが関連する場合があります。
      • 例えば、htmlWhitespaceSensitivity: "ignore" に設定すると、HTML内のホワイトスペースをより柔軟に扱うようになりますが、これが bracketSameLine の挙動に影響を与える可能性もゼロではありません。
  • Prettierのバグや制約
    • ごく稀に、特定のケースでPrettierのパーサーが正しく構造を認識できず、bracketSameLine のルールが適用されないバグが存在する場合があります。GitHubのPrettierリポジトリで同様のIssueが報告されていないか確認するか、自分でIssueを報告することを検討してください。

CI/CDパイプラインでのエラー

ローカルでは問題ないのに、CI/CDパイプラインでPrettierがエラーを吐くことがあります。

  • EOL (End of Line) の問題
    • WindowsとLinux/macOSで改行コード(CRLF vs LF)が異なるために、Prettierが異なる出力を生成し、--check でエラーになることがあります。
    • 解決策
      .prettierrcendOfLine: "lf" を明示的に設定し、すべての環境でLF改行を使用するように統一します。また、Gitの設定で core.autocrlf を適切に設定することも重要です。
  • --check フラグの使用
    • CI/CDでは prettier --check を使用して、フォーマットされていないファイルがないかを検証することが一般的です。この際に、期待通りのフォーマットが適用されていないとエラーになります。
  • 環境の差異
    • ローカルと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>

解説

  • 閉じタグの > は、最後の属性が記述されている行の末尾に配置されています。
  • すべての要素(buttondivMyComponent)において、属性が複数行にわたって記述されています。

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-reacteslint-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以外のフォーマッターを検討する、という流れになります。