PrettierのPrint Widthでよくあるエラーと解決策
Prettierにおける「Print Width」とは、コードの1行の最大文字数を指します。Prettierは、この設定値に基づいて、コードを自動的に整形し、指定された幅を超えないように改行を行います。
もう少し詳しく説明します。
-
例外: Prettierは賢く、必ずしもすべての行をPrint Widthに収めるわけではありません。例えば、長い文字列リテラルやURLなど、分割すると可読性が著しく低下する場合などは、Print Widthを超えてもそのままにする場合があります。
-
一般的な値:
- よく使われる値は80文字や120文字です。
- 歴史的に80文字が使われることが多かったですが、最近ではより広いディスプレイを使用する人が増えたため、120文字など、より大きな値を設定するプロジェクトも増えています。
- チームや個人の好みに合わせて設定できます。
-
設定方法:
- 通常は、プロジェクトのルートにある
.prettierrc
のような設定ファイルでprintWidth
というオプションを設定します。 - 例:
この場合、Prettierは1行の最大文字数を80文字に制限します。{ "printWidth": 80 }
- 通常は、プロジェクトのルートにある
-
動作: Prettierは、コードを整形する際に、各行がPrint Widthで指定された文字数を超えないように調整します。例えば、関数呼び出しの引数が長くなったり、配列の要素がたくさんあったりする場合、Prettierは自動的にそれらを複数行に分割してくれます。
-
目的: プロジェクト全体のコードスタイルを統一し、可読性を向上させることです。1行が長すぎると、横スクロールが必要になったり、コード全体の構造が把握しにくくなったりします。Print Widthを設定することで、この問題を解決します。
Prettier が printWidth の設定を無視する
よくある原因
- エディタの再起動が必要
- 設定ファイルを変更した後、エディタ(VS Codeなど)を再起動しないと、変更が反映されないことがあります。
- 他のフォーマッターとの競合
- ESLint や他のコードフォーマッターが Prettier と同時に有効になっていて、設定が競合している場合があります。特に ESLint の
max-len
ルールと Prettier のprintWidth
は混同されがちです。
- ESLint や他のコードフォーマッターが Prettier と同時に有効になっていて、設定が競合している場合があります。特に ESLint の
- ファイルの種類が対応していない
- Prettier は、デフォルトで全てのファイル形式に対応しているわけではありません。特定のファイル形式(例:
.tsx
)を整形するには、別途プラグインのインストールが必要な場合があります。
- Prettier は、デフォルトで全てのファイル形式に対応しているわけではありません。特定のファイル形式(例:
- 設定ファイルが読み込まれていない
.prettierrc
、prettier.config.js
、.prettierrc.json
などの設定ファイルがプロジェクトのルートに正しく配置されていない。- VS Codeなどのエディタ拡張機能が、プロジェクトの設定ではなく、グローバル設定を読み込んでいる可能性がある。
トラブルシューティング
- エディタの再起動
- 設定変更後は、エディタを完全に再起動してみてください。
- Prettier の出力ログを確認
- VS Code の「出力」タブで「Prettier」を選択し、フォーマット実行時のログを確認します。エラーメッセージや設定の読み込み状況が表示される場合があります。
- 競合する拡張機能の無効化
- 一時的に ESLint などの他のフォーマッター関連の拡張機能を無効にして、Prettier の動作を確認します。
- ESLint と Prettier を併用する場合は、
eslint-config-prettier
やeslint-plugin-prettier
を利用して、競合するルールを無効化する設定が必要です。
- .editorconfig の確認
.editorconfig
ファイルがプロジェクトに存在する場合、max_line_length
の設定が Prettier のprintWidth
を上書きしている可能性があります。.editorconfig
の設定も確認してください。
- エディタ設定の確認
- VS Codeの場合、
settings.json
でeditor.defaultFormatter
がesbenp.prettier-vscode
に設定されているか確認します。 - また、特定の言語のフォーマッターが上書きされていないか確認します(例:
"[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }
)。
- VS Codeの場合、
- 設定ファイルの確認
- プロジェクトのルートに
.prettierrc
やprettier.config.js
などの設定ファイルが正しく存在するか確認します。 - 設定ファイル内の
printWidth
オプションの値を確認します(例:printWidth: 120
)。
- プロジェクトのルートに
printWidth を超えても改行されないケースがある
よくある原因
- 特定の構文の例外ルール
- Prettier には、特定の構文(JSX、HTMLなど)に対して、
printWidth
とは別に独自の整形ルールが存在する場合があります。例えば、HTMLのインライン要素内の空白はprintWidth
の影響を受けにくいことがあります。
- Prettier には、特定の構文(JSX、HTMLなど)に対して、
- printWidth は「厳密な上限」ではない
- Prettier の
printWidth
は、あくまで「目安」であり、厳密な行の長さの上限ではありません。Prettier は、可読性を損なわずに整形できる範囲でprintWidth
を遵守しようとします。 - 例えば、非常に長い文字列リテラルやURL、分割すると意味が変わってしまうコードブロックなどは、
printWidth
を超えても改行されないことがあります。
- Prettier の
トラブルシューティング
- エディタの「ソフトラップ(折り返し)」機能を利用する
- Prettier で強制的に改行させたくないが、視覚的に長い行を折り返して表示したい場合は、エディタのソフトラップ(Word Wrap)機能を有効にするのが最も簡単な解決策です。これはコードの実際の改行には影響せず、表示上のみ折り返されます。
- printWidth の値を調整する
- もし、多くの箇所で
printWidth
を超える行が頻繁に発生し、それが視覚的に問題となる場合は、printWidth
の値を少し大きくする(例: 80 → 120)ことを検討します。ただし、これは問題の根本的な解決にはなりません。
- もし、多くの箇所で
- コードの構造を見直す
- 長すぎる行は、そもそもコードの書き方自体に問題がある可能性があります。変数を導入して式を短くしたり、関数を分割したりするなど、コードの構造自体を見直すことを検討します。
- // prettier-ignore コメントの利用
- Prettier に整形させたくない特定の行やブロックがある場合、その直前に
// prettier-ignore
コメントを追加することで、その部分の整形をスキップさせることができます。 - これは、一時的な対処法として有効ですが、多用するとコードスタイルの一貫性が損なわれる可能性があります。
- Prettier に整形させたくない特定の行やブロックがある場合、その直前に
よくある原因
- 改行コードの違い
- Windows と Linux/macOS で改行コード(CRLF vs LF)の違いがある場合、意図しない差分が生じることがあります。
- Prettier の実行設定が誤っている
- Git の pre-commit hook や CI/CD パイプラインで Prettier を実行する際のコマンドや設定が間違っている。
- 異なる Prettier バージョン
- 開発環境と CI/CD 環境で Prettier のバージョンが異なると、整形結果が異なる場合があります。
- 改行コードの設定
.prettierrc
でendOfLine: "lf"
を設定し、改行コードを統一します。- Git の
.gitattributes
ファイルに* text=auto eol=lf
を追加することで、Git が自動的に改行コードを変換するのを防ぎ、LF に統一することができます。
- --check フラグの利用
- CI/CD パイプラインでは、
prettier --check .
のように--check
フラグを付けて実行し、整形が必要なファイルがないか確認します。差分があればエラーとして扱います。
- CI/CD パイプラインでは、
- Prettier のバージョンを固定する
package.json
に Prettier のバージョンを明示的に記述し、npm install
やyarn install
で常に同じバージョンがインストールされるようにします。
例1: 基本的な関数の引数と printWidth
printWidth: 80
の場合
元のコード (整形前)
function calculateTotalAmount(price, quantity, discountPercentage, taxRate) {
const subtotal = price * quantity;
const discountedPrice = subtotal * (1 - discountPercentage);
const total = discountedPrice * (1 + taxRate);
return total;
}
Prettier で整形後 (printWidth: 80)
function calculateTotalAmount(
price,
quantity,
discountPercentage,
taxRate
) {
const subtotal = price * quantity;
const discountedPrice = subtotal * (1 - discountPercentage);
const total = discountedPrice * (1 + taxRate);
return total;
}
解説
printWidth: 80
の場合、calculateTotalAmount
関数の引数が1行に収まらないため、Prettier は自動的に引数を複数行に分割し、インデントを調整します。これにより、コードの可読性が向上します。
printWidth: 120
の場合
Prettier で整形後 (printWidth: 120)
function calculateTotalAmount(price, quantity, discountPercentage, taxRate) {
const subtotal = price * quantity;
const discountedPrice = subtotal * (1 - discountPercentage);
const total = discountedPrice * (1 + taxRate);
return total;
}
解説
printWidth: 120
の場合、関数の引数が1行に収まるため、Prettier は改行を行いません。
例2: 配列とオブジェクトリテラル
元のコード (整形前)
const fruits = ["apple", "banana", "orange", "grape", "kiwi", "strawberry", "melon", "pineapple"];
const userProfile = {
firstName: "John",
lastName: "Doe",
age: 30,
email: "[email protected]",
address: {
street: "123 Main St",
city: "Anytown",
zipCode: "12345",
country: "USA",
},
};
Prettier で整形後 (printWidth: 80)
const fruits = [
"apple",
"banana",
"orange",
"grape",
"kiwi",
"strawberry",
"melon",
"pineapple",
];
const userProfile = {
firstName: "John",
lastName: "Doe",
age: 30,
email: "[email protected]",
address: {
street: "123 Main St",
city: "Anytown",
zipCode: "12345",
country: "USA",
},
};
解説
printWidth: 80
では、fruits
配列の要素が1行に収まらないため、Prettier は各要素を個別の行に分割します。
userProfile
オブジェクトも同様に、ネストされた address
オブジェクトを含め、各プロパティが整形されます。
Prettier で整形後 (printWidth: 120)
const fruits = ["apple", "banana", "orange", "grape", "kiwi", "strawberry", "melon", "pineapple"];
const userProfile = {
firstName: "John",
lastName: "Doe",
age: 30,
email: "[email protected]",
address: {
street: "123 Main St",
city: "Anytown",
zipCode: "12345",
country: "USA",
},
};
解説
printWidth: 120
の場合、fruits
配列は1行に収まるため、改行は行われません。userProfile
オブジェクトは、ネストが深いため、printWidth
が大きくても各プロパティが複数行に分割される可能性があります。これは、オブジェクトの可読性を保つための Prettier の内部ルールによるものです。
例3: JSX (React)
元のコード (整形前)
function MyComponent({ title, description, imageUrl, buttonText, onClickButton }) {
return (
<div className="card">
<h2 className="card-title">{title}</h2>
<p className="card-description">{description}</p>
<img src={imageUrl} alt="Card Image" className="card-image" />
<button className="card-button" onClick={onClickButton}>{buttonText}</button>
</div>
);
}
Prettier で整形後 (printWidth: 80)
function MyComponent({
title,
description,
imageUrl,
buttonText,
onClickButton,
}) {
return (
<div className="card">
<h2 className="card-title">{title}</h2>
<p className="card-description">{description}</p>
<img src={imageUrl} alt="Card Image" className="card-image" />
<button className="card-button" onClick={onClickButton}>
{buttonText}
</button>
</div>
);
}
解説
JSX の props が多い場合も、printWidth
を超えると Prettier は自動的に改行を行います。特に、button
タグのように中身がある場合は、その中身も改行して整形されます。
Prettier で整形後 (printWidth: 120)
function MyComponent({ title, description, imageUrl, buttonText, onClickButton }) {
return (
<div className="card">
<h2 className="card-title">{title}</h2>
<p className="card-description">{description}</p>
<img src={imageUrl} alt="Card Image" className="card-image" />
<button className="card-button" onClick={onClickButton}>
{buttonText}
</button>
</div>
);
}
解説
printWidth: 120
でも、JSX の props は1行に収まる可能性がありますが、Prettier は JSX の開始タグと終了タグの可読性を考慮して、特定のパターンで改行を行うことがあります。この例では、button
タグの中身は printWidth
の影響を受けずに改行される可能性が高いです。
これらの例は、通常、プロジェクトのルートにある .prettierrc
ファイルで printWidth
オプションを設定することで実現されます。
.prettierrc ファイルの例 (JSON形式)
{
"printWidth": 80,
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"trailingComma": "es5"
}
または、JavaScript 形式でコメントを記述することも可能です。
module.exports = {
printWidth: 120, // 1行の最大文字数を120に設定
tabWidth: 2, // インデント幅を2に設定
semi: true, // 文末のセミコロンを強制
singleQuote: true, // シングルクォートを使用
trailingComma: 'es5', // オブジェクトや配列の末尾にカンマを付ける (ES5互換)
};
Prettier の他のオプションで printWidth の動作を微調整する
これは厳密には「代替」ではありませんが、printWidth
を補完・微調整する Prettier 自身のオプションについて理解することは重要です。
singleAttributePerLine
: HTML、Vue、JSX の要素の属性を1行に1つずつ配置するかどうかを制御します。printWidth
が小さい場合に、属性が自動的に複数行に分割されるのを助けます。htmlWhitespaceSensitivity
: HTML、Vue、Angular、Handlebars の空白の扱いを制御します。css
、strict
、ignore
などの値があり、HTML タグ内のテキストやインライン要素の改行に影響を与えることがあります。これにより、printWidth
で強制的に改行されるのを防いだり、逆に意図した改行を促したりできます。proseWrap
: Markdown のような散文的なテキスト(プログラミングコードではない部分)に対する改行の挙動を制御します。always
(常にprintWidth
で折り返す)、never
(折り返さない)、``preserve`(元の改行を保持する)などの値があります。特に Markdown ドキュメントを Prettier で整形する場合に重要になります。
なぜ重要か
これらのオプションは、printWidth
が意図しない改行を引き起こす場合や、特定のファイルタイプでprintWidth
の挙動をより細かく制御したい場合に役立ちます。printWidth
だけでは解決できない見た目の問題を解決できることがあります。
コードの構造自体を見直す(リファクタリング)
これは Prettier の設定そのものではありませんが、printWidth
を超える行が頻繁に発生する場合の最も根本的な解決策の一つです。
- ネストの深さの削減:
if
文やfor
ループ、関数呼び出しなどが深くネストしていると、インデントが増えてprintWidth
を圧迫します。早期リターン(ガード句)の使用、小さい関数への分割、戦略パターンの適用などでネストを浅くすることを検討します。 - インライン化の回避: 複雑な条件式や計算を直接 JSX や関数の引数にインラインで記述すると、行が長くなりがちです。これらを別の変数に抽出したり、ヘルパー関数にカプセル化したりすることで、コードの可読性を高め、行の長さを短縮できます。
- 長いチェーンメソッドの分割:
someArray.filter(...).map(...).sort(...).forEach(...)
のように長いメソッドチェーンは、printWidth
に収まりにくく、途中の処理が分かりにくくなることがあります。中間変数を導入したり、各処理を個別の関数に分離したりすることで、コードをより読みやすく、printWidth
に収まるようにできます。
なぜ重要か
printWidth
はあくまで表面的な整形ツールです。根本的に行が長すぎるコードは、設計上の問題(凝集度の低さ、結合度の高さなど)を抱えている可能性があります。コードの構造自体を改善することで、より保守しやすく、理解しやすいコードになります。
エディタの表示設定で対応する(ソフトラップ/Word Wrap)
これはコードの整形とは異なりますが、表示上の問題を解決するための代替手段です。
- ソフトラップ (Word Wrap): 多くのモダンなエディタ(VS Code, Sublime Text, JetBrains IDEsなど)には「ソフトラップ」または「単語の折り返し」機能があります。これを有効にすると、
printWidth
を超える行があった場合でも、実際の改行コードを挿入することなく、表示上のみ次の行に折り返して表示されます。
なぜ重要か
- 特定の長い行への対処: Prettier があえて改行しないような長い文字列リテラルや URL など、意味的に分割できない行を視覚的に見やすくしたい場合に非常に有効です。
- 柔軟な表示: ユーザーは自分の好みに合わせてエディタの表示幅を調整でき、それに合わせてコードが自動的に折り返されるため、個々の環境での可読性を最適化できます。
- ファイルサイズへの影響なし: 実際の改行コードが挿入されないため、ファイルのサイズが増えたり、Git の差分が不要に増えたりすることがありません。
注意点
これはあくまで表示上の問題解決であり、Prettier の整形ルールとは直接関係ありません。コードベース全体の整形ルールを統一したい場合は、やはり Prettier の printWidth
設定が重要になります。
ESLint の max-len ルールとの連携(非推奨だが考慮事項)
かつては ESLint の max-len
ルールと Prettier の printWidth
が似たような機能を持っていたため、どちらを使うか、あるいはどう連携させるかが議論の対象でした。
max-len
(ESLint): ESLint には、1行の最大文字数を制限するmax-len
ルールがあります。このルールは、code
、comments
、ignorePattern
など、より詳細な設定が可能です。
現在の推奨
**基本的には、行の長さの整形に関しては Prettier の printWidth
に一任し、ESLint の max-len
ルールは無効化するか、Prettier と競合しないように設定することが強く推奨されています。**これは、eslint-config-prettier
を利用することで簡単に実現できます。
なぜ非推奨か
- Prettier の優位性: Prettier はフォーマッターに特化しており、行の長さの整形においてより高度なロジックを持っています。単に行の長さをチェックするだけでなく、読みやすさを考慮した上で最適な位置で改行を行います。
- 競合と混乱: Prettier と ESLint の両方で行の長さを制御しようとすると、設定が競合したり、意図しない挙動になったりして、開発者に混乱を招きます。
Prettier の printWidth
は、コード整形における「行の長さ」を定義する標準的な方法であり、ほとんどのプロジェクトでこれを中心に据えるべきです。しかし、上記の代替方法や補完的なアプローチを理解することで、より複雑な整形要件に対応したり、コードの根本的な品質改善に取り組んだり、あるいは開発者の視覚的な好みにも対応したりすることが可能になります。
- ESLint との連携: 行の長さの整形は Prettier に一任し、ESLint との競合を避ける設定を行う。
Prettierの
printWidth
は、コードの自動整形において非常に強力なツールですが、その「意見が強い(opinionated)」という性質から、特定のユースケースでは代替手段や補完的なアプローチを検討することもあります。 - エディタのソフトラップ: 表示上の問題であれば、エディタの機能で解決する。
- リファクタリング:
printWidth
を超えるコードが多い場合は、コードの構造そのものに改善の余地がないか考える。 - Prettier の微調整:
printWidth
だけでは解決しない見た目の問題には、proseWrap
やhtmlWhitespaceSensitivity
などのオプションを検討する。
ESLint の max-len ルール
max-len
(maximum line length) は、ESLint のルールの一つで、1行の最大文字数を強制することができます。Prettier の printWidth
と似ていますが、以下の点で異なります。
- ESLint の max-len
これは「厳密な上限」として機能します。指定された文字数を超えると、警告(warning)またはエラー(error)として報告されます。 - Prettier の printWidth
あくまで「目安」であり、Prettier は可読性を損なわずに整形できる範囲でこの幅を目指します。長い文字列リテラルなど、Prettier が分割すべきではないと判断した場合は、printWidth
を超えることがあります。
使い分けの例
- Prettierを使用せず、ESLintのみでフォーマットする場合
Prettierのような自動フォーマッターを導入せず、ESLint のルールのみでコードスタイルを管理したい場合にmax-len
を使用します。この場合、ESLint の自動修正機能(eslint --fix
)で一部の整形を行うことができますが、Prettierほど網羅的ではありません。 - Prettierと併用する場合
一般的に、Prettier と ESLint を併用するプロジェクトでは、eslint-config-prettier
を利用して、ESLint の整形に関するルール(max-len
を含む)を無効にすることが推奨されます。これにより、Prettier と ESLint のルールが競合するのを防ぎ、Prettier にフォーマットを一任します。- ただし、例外
Prettier が整形しないような極端に長い行(例:超長文のコメントなど)に対してのみ、ESLint のmax-len
を警告として設定し、開発者に注意を促すといった使い方をするケースもあります。
- ただし、例外
設定例 (.eslintrc.js)
module.exports = {
// ...その他のESLint設定
rules: {
// Prettierと併用する場合は通常offにするか、eslint-config-prettierで無効化される
// 'max-len': ['error', { code: 100, ignoreComments: true, ignoreUrls: true }],
// 例:Prettierが整形しないコメントの長さを警告する場合
'max-len': ['warn', { code: 120, ignoreStrings: true, ignoreTemplateLiterals: true, ignoreUrls: true }],
},
};
EditorConfig の max_line_length
EditorConfig は、様々なエディタやIDE間でコードスタイルを統一するためのファイル形式です。.editorconfig
ファイルをプロジェクトのルートに配置することで、インデントのスタイル、タブの幅、改行コード、そして行の最大長などを設定できます。
- エディタ/IDEとの連携
.editorconfig
は、多くのエディタ(VS Code, IntelliJ IDEA, Sublime Textなど)がネイティブでサポートしているため、Prettierを使わない環境でも基本的なコードスタイルを統一するのに役立ちます。 - Prettierとの連携
Prettier は、デフォルトで.editorconfig
ファイルを読み込み、そこにmax_line_length
が設定されていれば、その値をprintWidth
として使用します(ただし、.prettierrc
でprintWidth
が明示的に設定されている場合はそちらが優先されます)。
設定例 (.editorconfig)
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 100 # 1行の最大文字数を100に設定
メリット
Prettier がインストールされていない環境や、特定のファイルタイプ(Prettier がサポートしていない言語など)に対しても、基本的な行の長さを統一するのに使えます。
これはコードの整形方法ではありませんが、長い行の表示に関する「代替」として考慮されることがあります。
- 使いどころ
- Prettier に強制的に改行させたくないが、横スクロールは避けたい場合に有効です。
- 特に、Prettier が改行を避けるような長い文字列リテラルやURLなどに対して、視覚的な読みやすさを確保するために利用できます。
- Prettierとの違い
- Prettier の
printWidth
は、実際にコードファイル内の改行を挿入して整形します。 - ソフトラップは、あくまで「表示上の折り返し」であり、実際のファイル内容には変更を加えません。
- Prettier の
- 機能
多くのエディタやIDEには、設定された行の長さやウィンドウの幅に合わせて、表示上のみ行を折り返す「ソフトラップ」または「単語の折り返し(Word Wrap)」機能があります。
設定例 (VS Code)
settings.json
または VS Code の設定UIで editor.wordWrap
を on
に設定します。
{
"editor.wordWrap": "on"
}
Prettier 以外にも、コードの整形やスタイルの強制を行うツールは存在します。これらの中には、printWidth
に相当する設定を持つものや、より詳細なカスタマイズが可能なものもあります。
- 言語固有のフォーマッター
- Go言語の
gofmt
、Rust言語のrustfmt
、PythonのBlack
など、特定のプログラミング言語に特化した公式または推奨のフォーマッターがあります。 - これらは通常、その言語のベストプラクティスに従った非常に意見の強い整形を行います。多くの場合、
printWidth
に相当するような厳密な行の長さのオプションは存在せず、ツールが最適な行の長さを判断します。
- Go言語の
- JS Beautifier (js-beautify)
- JavaScript、HTML、CSS を整形するためのツールです。
indent_size
やmax_preserve_newlines
など、より多くの整形オプションを提供します。max_line_length
のような直接的なprintWidth
に代わるオプションはありますが、Prettier ほど構文解析に基づいてインテリジェントに改行を行うわけではありません。
- StandardJS
- 「設定なし(zero-config)」を哲学とする、非常に意見が強い(opinionated)JavaScriptのスタイルガイド兼リンター兼フォーマッターです。
printWidth
に相当する直接的な設定はありませんが、StandardJS のルールセットに従って自動的に整形されます。- Prettier と同様に、開発者がスタイルの議論に時間を費やすのを避けることを目的としています。
- 他のフォーマッター/リンター
Prettier の意見が強いアプローチが合わない場合や、より詳細なカスタマイズが必要な場合。 - エディタのソフトラップ
ファイル内容を変更せず、表示上の長い行を折り返したい場合。 - EditorConfig の max_line_length
エディタ間の設定統一や、Prettier を使わない環境での基本的なスタイル強制に。 - ESLint の max-len
Prettier との競合を避けつつ、特定の状況で厳密な行の長さを強制したい場合。