設定ファイル
毎回フラグを指定する代わりに、svelte-vitals.config で一度だけ設定します。
--rules、--ignore、--fail-on、--weights を実行のたびに指定する代わりに、プロジェクトルートに svelte-vitals.config ファイルを置いて設定をまとめられます。CLI と Vite プラグイン はいずれもこのファイルを自動的に読み込みます(Vite プラグインは直接読み込みます。詳細は下記の Vite プラグインで設定ファイルを再利用する を参照)。
svelte-vitals install --client config-file を実行すると、以下のオプションをすべてコメントアウトした状態の雛形を生成できます。
探索場所
svelte-vitals は次のファイルを、この優先順で分析対象ディレクトリのみから探します(親ディレクトリへの上方探索は行いません。分析対象ディレクトリは SvelteKit プロジェクトのルートであり、vite.config.* が置かれている場所と同じです):
svelte-vitals.config.jssvelte-vitals.config.ts
最初に見つかったファイルを使います。どれも存在しなければ、この機能がなかった頃と同じく、svelte-vitals は組み込みのデフォルト設定で動きます。
install --client config-file が .ts を選ぶのは次の2条件がそろったときです。プロジェクトが TypeScript 志向であること(ルートに tsconfig.json または vite.config.ts)、かつ svelte-vitals が依存関係として宣言されていること。defineConfig の import は読み込み時に解決されるため、npx だけで使うプロジェクトには適用できません。
それ以外は .js を書き出します。どちらのファイルも ESM なので、プロジェクトは "type": "module"(SvelteKit のデフォルト)である必要があり、CommonJS プロジェクトはサポートされません。--force は既存ファイルの拡張子を維持し、形式を勝手に切り替えません。
特定の設定ファイルを指定して分析したい場合は --config <path> を使います。指定すると探索は行われず、その設定ファイルだけが使われます(マージはされません)。相対パスの基準は、解析対象ディレクトリではなくコマンドを実行したディレクトリです。たとえばリポジトリのルートで svelte-vitals apps/web --config shared/sv.config.js を実行すると、読み込まれるのは ./shared/sv.config.js です。受け付ける拡張子は .js と .ts のみで、ファイルが存在しない・読み込めない場合は exit 2 で終了します。設定をコミットする前に試したいとき、モノレポ内の複数アプリで一つの設定を共有したいときに使えます。
--config は CLI 専用のフラグです。Vite プラグインは従来どおり svelteVitals({ ... }) に渡した cwd(未指定なら Vite の設定ルート)から設定を解決します(後述)。プラグインにも同じ設定を共有したい場合は、共有ファイルを vite.config.ts で import してプラグインのオプションに展開してください。オプションは探索された設定ファイルより優先されます。
例
// svelte-vitals.config.ts
import { defineConfig } from 'svelte-vitals';
export default defineConfig({
treatDynamicAs: 'warn',
metaComponents: ['Seo'],
rules: {
'seo/json-ld': 'off'
},
failOn: 'warning',
weights: {
seo: 2
}
});// svelte-vitals.config.js
export default {
treatDynamicAs: 'warn',
metaComponents: ['Seo'],
rules: {
'seo/json-ld': 'off'
},
failOn: 'warning',
weights: {
seo: 2
}
};defineConfig は、渡したオブジェクトを組み込みのデフォルトにマージするだけの薄いヘルパーで、.ts ファイルでの型チェックとエディタの補完のために存在します。プレーンな export default {...} オブジェクトでも実行時の挙動はまったく同じです。.js ファイルではどちらにしても型チェックの恩恵はないので、(JavaScript タブが示すように)プレーンなオブジェクトのままで構いません。しかも import と違い、svelte-vitals を npx 経由でしか実行せず node_modules に存在しない場合でも動作します。
.ts 設定内の defineConfig の import はランタイムの import であり、型チェック時だけでなく、svelte-vitals がファイルを読み込む時に解決されます。そのため、プロジェクトの依存関係として svelte-vitals が宣言されている必要があります。import 元は、実際にインストールしているパッケージである svelte-vitals にしてください。(@svelte-vitals/core からも re-export されていますが、このパッケージは通常は推移的な依存関係であり、pnpm のデフォルトである厳格な node_modules の構成では、プロジェクトから推移的な依存関係を直接解決できません。)
利用可能なオプション
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
treatDynamicAs |
'pass' | 'warn' | 'fail' |
'pass' |
メタデータの値が動的に設定されているルートをどう採点するか |
metaComponents |
string[] |
[] |
解析が追跡できない <head> メタデータ出力コンポーネント名(npm パッケージ由来など)。解決できるリポジトリ内のコンポーネントは自動的に追跡される |
rules |
Record<string, 'off' | 'critical' | 'warning' | 'info' | { severity?, options? }> |
{} |
ルールごとの上書き(ルールを無効化する、重大度を変更する、オプションを設定する) |
failOn |
'critical' | 'warning' | 'info' |
'critical' |
実行を失敗させる(終了コード 1)最低重大度 |
weights |
Partial<Record<Category, number>> |
各カテゴリ 1 |
組み合わせた Health スコア のカテゴリごとの重み |
overrides |
RuleOverride[] |
(なし) | ルート/ファイル単位のルール上書き(下記を参照) |
Category は 'seo' | 'performance' | 'correctness' | 'security' | 'architecture' | 'a11y' です。
重み 0 は正当な値で、そのカテゴリを Health の平均から完全に除外します(カテゴリ自体のスコアは引き続き出力され、検出結果や終了コードの挙動にも影響しません)。ただし、結果に存在するすべてのカテゴリを 0 にすると平均の取りようがなくなるため、実行はエラー(終了コード 2)になります。
ルールをルートやファイルにスコープする (overrides)
rules は全体に適用されます。overrides はマッチした箇所にだけルール設定を適用します。典型的なのは、意図的に非公開のルート(認証必須のページ)を SEO メタデータルールの対象外にしたいケースです:
export default {
overrides: [
// (app) ルートグループ配下:SEO チェックを一切行わない。
{ files: 'src/routes/(app)/**', rules: { seo: 'off' } },
// /admin とその配下:seo/title-presence は残すが info に格下げ。
{ route: '/admin/**', rules: { 'seo/title-presence': 'info' } }
]
};
各エントリは rules(キーはルール ID またはカテゴリ名、値は 'off' | 'critical' | 'warning' | 'info'、または後述のルールオプションで説明するオブジェクト形式)と、少なくとも1つのスコープを持ちます:
route:レポートに表示されるルート ID(例:/blog/[slug])にマッチする glob。SvelteKit の(group)セグメントはルート ID に含まれない点に注意してください(src/routes/(app)/dashboardは/dashboardとして報告されます)。グループを対象にするにはfilesを使います。files:検出結果のソースパス(例:src/routes/(app)/dashboard/+page.svelte)にマッチする glob。
glob の構文はあえて最小限に絞ってあります:* はパスセグメント内にマッチ、** はセグメントをまたいでマッチ、末尾の /** はプレフィックス自体にもマッチします(/admin/** は /admin そのものにもマッチ)。それ以外((、)、[、] を含む)はすべてリテラルです。エントリは route / files の glob のいずれかがマッチしたときにマッチします。
押さえておきたい挙動:
'off'はマッチした検出結果を完全に取り除きます。実行を失敗させず、スコアも下げません。そのルールがそこでは実行されなかったのと同じ扱いです。一方、重大度の値を指定した場合は、取り除くのではなくその重大度に再分類します。- エントリは順に評価され、後のエントリが勝ちます。1つのエントリ内では、ルール ID のキーが重大度を指定している場合に限りカテゴリのキーに勝ちます。オプションだけを持つ(
severityを指定しない)ルール ID のキーはオプションだけを反映し、カテゴリのキーの重大度はそのまま有効であり続け、上書きはしません。マッチした箇所ではオーバーライドが常にグローバルのrules設定に勝ちます。 - ルートにもファイルにも紐付かない検出結果(robots.txt などプロジェクト全体のチェック)には一切影響しません。そちらは
rulesを使ってください。 overridesが効くのは CLI と Vite プラグインのビルド時ゲートです。ライブダッシュボードのリクエストごとのレイヤーは、ページがレンダリングされるたびにその場でスコアリングするため overrides を適用しません。追加したばかりのオーバーライドを確認するときは、CLI(またはビルドゲート)を正とみなしてください。- 「アプリのこの部分は恒久的に対象外」というポリシーには、suppressions ファイルより
overridesを選んでください:suppressions はファイルを書き出した時点で存在した検出結果だけを受け入れるため、あとから追加したルートは再び失敗します。overrides は同じ glob 配下の新しいルートにもマッチし続けます。
ルールオプション
単なる重大度の文字列に加えて、ルール設定にはオブジェクト形式 { severity?, options? } も指定できます:
export default {
rules: {
'architecture/prop-count': { options: { max: 10 } },
'performance/heavy-import': { options: { packages: { 'chart.js': 'import chart.js/auto' } } }
},
overrides: [{ files: 'src/lib/**', rules: { 'architecture/prop-count': { options: { max: 4 } } } }]
};
severity は省略可能です。省略すると、そのルールの組み込みの重大度を保ったままオプションだけを変更できます。{ severity: 'off', ... } はいつも通りそのルールを無効化し、一緒に指定した options はその場合無効(inert)になります。文字列だけの形式('off'、'critical'、'warning'、'info')も変わらず使えます。オブジェクト形式はそれらを置き換えるものではなく、追加の選択肢です。
オプションは overrides エントリの中でもトップレベルの rules マップと同じように使え、他の override 設定と同様に route / files でスコープできます。ただし指定できるのはルール ID のキーだけで、カテゴリのキーには指定できません:カテゴリには重大度を指定できますが、オプションはどのルール向けかが分からなければ意味を持たないためです。
層は「組み込みのデフォルト → rules → マッチする overrides エントリを順に」の順で重なり、組み合わさり方はオプションの種類で決まります。
- 整数は置き換えです。最後に設定された値が勝ちます。
- リストとマップは、組み込みのセットを破棄せず追加します。以降のリリースで組み込みが増えても恩恵を受け続けられます。
- マップの既存キーは、エントリを残したまま値だけが指定値になります。1つのパッケージについて組み込みの対処方法だけを書き換えたいときに使います。
オプションを受け付けるのは一部のルールだけです。オプションを受け付けないルールに options を渡すのは、未知のオプション名や型の誤ったオプション値と同じく致命的な設定エラーになります。以下のルールはオプションを受け付け、それ以外のルールは重大度文字列 / off のみを受け付けます。各ルールのページには「設定」節があり、正確なオプション名とデフォルト値が書かれています。
architecture/prop-countとarchitecture/component-sizeは整数のmaxを取ります。seo/title-lengthとseo/description-lengthは整数のmin/maxを取ります。performance/heavy-importは、パッケージ指定子 → 対処方法の文字列というpackagesマップを取ります。組み込みリストに追加されます。performance/preconnectは、ホスト名のoriginsリストを 取ります。組み込みリストに追加されます。architecture/private-scope-importは、プライベートな ディレクトリを指定するscopesの glob リストを取ります。設定するまでこのルールは何も出力しません。architecture/unit-entry-fileは、どのディレクトリが ユニットかを宣言するunits/pascalCaseUnits/excludeの glob を取ります。設定するまでこのルールは 何も出力しません。architecture/directory-namingは、ディレクトリ glob → 記法の集合 のdirectoriesマップとexcludeの glob を取ります。directoriesを設定するまでこのルールは 何も出力しません。architecture/reserved-directory-namesは、scopes(ディレクトリ glob → 直下に置ける名前)、unitScopes(起点 glob → ユニット直下に置ける 名前)、anyCaseUnitScopes(同様、大文字小文字を問わないユニット用)、excludeを取ります。いずれかの スコープマップを設定するまで無効です。architecture/route-component-importは、 ルートエントリを手動でインポートしてよいサテライトファイル(stories、test、spec)を指定するexemptImportersの glob リストを取ります。組み込みリストに追加されます。architecture/doc-link-targetは、プロジェクトのルートを 表す URL プレフィックスを指定するurlRootsのリストを取ります。設定するまでこのルールは何も出力しません。
インポートエイリアス
インポートを追跡するルール(architecture/private-scope-import、architecture/route-component-import、
security/shared-state-import、security/handler-state-write)は、プロジェクトが svelte.config.{js,ts} で宣言しているエイリアス、つまり
kit.alias と、$lib を移動している場合の kit.files.lib を通じて指定子を解決します。svelte-vitals はこれらを
静的に、SvelteKit がエイリアスを構築するのと同じ順序で読み取り、ビルド時とまったく同じく最初にマッチ
したエイリアスが使われます。
CLI の静的モードは、ルートの <head> と見出しを解決するためにコンポーネントのインポートをたどる際にも
これらのエイリアスに従います($lib や相対インポートだけでなく、$components などのカスタムエイリアス
経由でインポートされたコンポーネントが設定する <title>/meta/JSON-LD/<h1> も対象になります)。そのため、
この経路を読む SEO 系ルールはすべて、どのエイリアスを経由してたどり着いたコンテンツかにかかわらず同じ
ように扱います。
以下のケースは解決されません:
- エイリアスの値が(
path.resolve(...)やテンプレートリテラルなどで)計算される場合。プレーンな文字列 ではないため、指定子は「見えないもの」として扱われ、何も報告されません。 - エイリアスの値がリテラルの絶対パスである場合。
/opt/shared/srcのような POSIX パスや、C:\shared\srcのような Windows のドライブレター付きパスなど。プロジェクトの外にあるファイルを指す ため、対象として扱いません。 kit.files.lib自体がプレーンな文字列ではなく計算される場合。この場合$lib自体が解決不能になるため、 上記のルールは$lib/...から始まる指定子に沈黙するだけでなく、security/handler-state-writeの libserver/免除も、 ディレクトリの移動先を推測せず無効のままになります。svelte.config.{js,ts}ではなくvite.config.tsのsveltekit()プラグインに SvelteKit のオプションを 渡しているプロジェクトの場合。この場合も同様に何も報告されません。kit.aliasオブジェクトにスプレッド({ ...shared, '$a': 'src/a' })や計算されたキー ({ [key]: 'src/a' })が含まれる場合。未知のキーはそれより後ろに宣言されたどのエントリでも上書き しうるため、そのエントリ1つだけでなくkit.alias全体が読み取り不能として扱われます。隣に書か れたリテラルなエイリアスも、これに引きずられて解決されなくなります($libは常に先頭の位置を占め るため、何にも上書きされず影響を受けません)。
優先順位
各フィールドについて、次のうち最初に設定されているものが優先されます:CLI フラグ > 設定ファイル > 組み込みのデフォルト。この優先順位はフィールドごとに独立して働きます。一度きりの --fail-on info を指定しても、設定ファイルの他のフィールドはそのまま生きています。
一つ例外があります。--rules と --ignore はどちらも「どのルールを実行するか」を選ぶだけで、有効なままのルールをどう設定するかには関与しません。--rules は名前を挙げたルール ID に実行を絞り込み、その ID については設定ファイルのトップレベルの rules に書かれた off を上書きします。ルールを無効化することそのものが選択だからです。それ以外、名前を挙げたルールの重大度やオプションは設定ファイルの値をそのまま引き継ぎます。--ignore は向きが違うだけです。名前を挙げたルール ID に off エントリを追加するだけで、これは rules(設定ファイル、あるいは --rules によって絞り込まれた後の値)の上にレイヤーとして重ねて適用されます。名前を挙げていないルールには何も起こらず、直前のレイヤーが解決した値、すなわち設定ファイルの設定、あるいは --rules によって除外されていれば off を、そのまま保持します。両方が同じルールを名指ししたときは --ignore が --rules に勝ちます。プログラムから、あるいは Vite プラグインのオプションとして明示的に渡した rules の値は、これまで通り設定ファイルの rules を丸ごと置き換えます。
overrides に対応する CLI フラグはありません。ルートのポリシーはコミットされるファイルに置くべきものだからです。CLI と Action にとっては設定ファイルが唯一のソースで、Vite プラグインだけは追加でプラグインオプションとしても受け取ります(いつも通り、オプション > ファイル)。
バリデーション
- 無効で svelte-vitals が停止する(終了コード
2)(構文エラー、または default export がない場合)、rules内に未知のルール ID がある、weights内に未知のカテゴリまたは負の値や数値でない値がある場合、overridesのエントリが不正な場合({ route/files, rules }の形でない、スコープが文字列でも空でない文字列配列でもない、rules内のキーが既知のルール ID でもカテゴリ名でもない)、rulesまたはoverridesエントリのrules内のルール設定が不正な場合(off/critical/warning/info以外の文字列、未知のキーを含むオブジェクト形式、オブジェクト内の不正なseverity、オプションを受け付けないルールへのoptions、未知のオプション名、型が誤っているか範囲外、またはオプションが宣言する文法に合わないオプション値(タグ名のリストにセレクタを書いた場合)、カテゴリのキーへのoptions、またはminとmaxの両方を持つルールでminがmaxを超える範囲になっている場合のいずれか)。 - 無効だが無視され、警告が出る(分析は続行される)
treatDynamicAsまたはfailOnの値(フラグ/デフォルトにフォールバック)、認識できないトップレベルキー(将来の設定フィールドとの前方互換性のため)。
TypeScript の設定ファイル
svelte-vitals.config.ts はサポート対象のすべての Node でそのまま動作します(最低要件の 24.16 以降は TypeScript の型をフラグなしでネイティブに除去します)。
Vite プラグインで設定ファイルを再利用する
@svelte-vitals/vite は CLI と同じ方法で svelte-vitals.config.* を読み込みます。追加の配線は不要です。ビルドゲートとライブダッシュボードのどちらも、プロジェクトルート(svelteVitals({ ... }) に渡す cwd、省略時は Vite の config root)から解決し、CLI と同じフィールド単位の優先順位を適用します: プラグインオプション > 設定ファイル > 組み込みのデフォルト。weights も含みます。
import { sveltekit } from '@sveltejs/kit/vite';
import { svelteVitals } from '@svelte-vitals/vite';
export default {
plugins: [sveltekit(), svelteVitals({ report: 'console' })]
};
プロジェクトルートに svelte-vitals.config ファイルを置くだけで、上記のプラグインはその treatDynamicAs / metaComponents / rules / failOn / weights / overrides を自動的に読み込みます。vite.config.ts 側で自分でファイルを import する必要はありません。設定ファイルの非致命的な警告(未知のトップレベルキー、無効な列挙値など)は、CLI と同じ svelte-vitals: というプレフィックス付きの文言でコンソールに出力されます。