Skip to content
14 changes: 14 additions & 0 deletions .changeset/route-component-import.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'@svelte-vitals/core': minor
'svelte-vitals': minor
'@svelte-vitals/vite': minor
'@svelte-vitals/mcp': minor
---

Add `architecture/route-component-import`, which reports a component importing a SvelteKit route entry
(`+page.svelte`, `+layout.svelte`, `+error.svelte`, and their `@` breakout forms).

This is the first Architecture rule that is **on by default**, so a project that changes nothing may see
new findings at `info`. Kit renders a route entry with the data it supplies; imported elsewhere the
component renders without it. Stories, tests and specs are exempt by default, and `exemptImporters`
extends that list for a project whose satellite files are named another way.
7 changes: 5 additions & 2 deletions docs/src/content/docs/guides/(setup)/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,14 @@ section with its exact option names and defaults.
- [`architecture/reserved-directory-names`](/rules/architecture/reserved-directory-names) — `scopes`
(directory glob → allowed child names), `unitScopes` (root glob → the names a unit's children may
take) and `exclude`. Off until one of the two is set.
- [`architecture/route-component-import`](/rules/architecture/route-component-import) — an
`exemptImporters` glob list of satellite files (stories, tests, specs) allowed to import a route
entry by hand, added to the built-in list.

### Import aliases

Rules that follow imports (`architecture/private-scope-import`, `security/shared-state-import`,
`security/handler-state-write`) resolve specifiers through the aliases your project declares in
Rules that follow imports (`architecture/private-scope-import`, `architecture/route-component-import`,
`security/shared-state-import`, `security/handler-state-write`) resolve specifiers through the aliases your project declares in
`svelte.config.{js,ts}` — `kit.alias`, plus `kit.files.lib` when `$lib` has been moved. They are read
statically, in the same order SvelteKit builds them, and the first matching alias wins, exactly as it
does at build time.
Expand Down
7 changes: 5 additions & 2 deletions docs/src/content/docs/ja/guides/(setup)/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,14 @@ export default {
- [`architecture/reserved-directory-names`](/ja/rules/architecture/reserved-directory-names) —
`scopes`(ディレクトリ glob → 直下に置ける名前)、`unitScopes`(起点 glob → ユニット直下に置ける
名前)、`exclude`。どちらかを設定するまで無効です。
- [`architecture/route-component-import`](/ja/rules/architecture/route-component-import) —
ルートエントリを手動でインポートしてよいサテライトファイル(stories、test、spec)を指定する
`exemptImporters` の glob リスト。組み込みリストに追加されます。

### インポートエイリアス

インポートを追跡するルール(`architecture/private-scope-import`、`security/shared-state-import`、
`security/handler-state-write`)は、プロジェクトが `svelte.config.{js,ts}` で宣言しているエイリアス —
インポートを追跡するルール(`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` — を通じて指定子を解決します。これらは
静的に、SvelteKit がエイリアスを構築するのと同じ順序で読み取られ、ビルド時とまったく同じく最初にマッチ
したエイリアスが使われます。
Expand Down
17 changes: 9 additions & 8 deletions docs/src/content/docs/ja/rules/architecture/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ description: svelte-vitals の Architecture ルール一覧。

コードの形と置き場所のサイン。コンポーネントの大きさ、props の数、そしてプロジェクトが宣言した import の境界を見ます。

| ルール | 重大度 | 概要 |
| ------------------------------------------------------------------------------------------ | ------- | ---------------------------------------------------------------------------------- |
| [`architecture/component-size`](/ja/rules/architecture/component-size) | 🔵 info | 大きくなりすぎたコンポーネントは分割しましょう。 |
| [`architecture/directory-naming`](/ja/rules/architecture/directory-naming) | 🔵 info | ディレクトリは、その場所に宣言した記法で名付けるべきです。 |
| [`architecture/private-scope-import`](/ja/rules/architecture/private-scope-import) | 🔵 info | プライベートなディレクトリ内のユニットを、その外から import すべきではありません。 |
| [`architecture/prop-count`](/ja/rules/architecture/prop-count) | 🔵 info | props が多すぎるコンポーネントは、担っている責務も多すぎます。 |
| [`architecture/reserved-directory-names`](/ja/rules/architecture/reserved-directory-names) | 🔵 info | ディレクトリの直下に置ける名前は、その位置に宣言した名前だけにすべきです。 |
| [`architecture/unit-entry-file`](/ja/rules/architecture/unit-entry-file) | 🔵 info | ユニットとして宣言したディレクトリには、同名のファイルを置くべきです。 |
| ルール | 重大度 | 概要 |
| ------------------------------------------------------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------- |
| [`architecture/component-size`](/ja/rules/architecture/component-size) | 🔵 info | 大きくなりすぎたコンポーネントは分割しましょう。 |
| [`architecture/directory-naming`](/ja/rules/architecture/directory-naming) | 🔵 info | ディレクトリは、その場所に宣言した記法で名付けるべきです。 |
| [`architecture/private-scope-import`](/ja/rules/architecture/private-scope-import) | 🔵 info | プライベートなディレクトリ内のユニットを、その外から import すべきではありません。 |
| [`architecture/prop-count`](/ja/rules/architecture/prop-count) | 🔵 info | props が多すぎるコンポーネントは、担っている責務も多すぎます。 |
| [`architecture/reserved-directory-names`](/ja/rules/architecture/reserved-directory-names) | 🔵 info | ディレクトリの直下に置ける名前は、その位置に宣言した名前だけにすべきです。 |
| [`architecture/route-component-import`](/ja/rules/architecture/route-component-import) | 🔵 info | SvelteKit のルートエントリはフレームワークが描画するものであり、他のコンポーネントから import するものではありません。 |
| [`architecture/unit-entry-file`](/ja/rules/architecture/unit-entry-file) | 🔵 info | ユニットとして宣言したディレクトリには、同名のファイルを置くべきです。 |

{/* rules-index:end */}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: architecture/route-component-import · ルートコンポーネントの import
description: SvelteKit のルートエントリはフレームワークが描画するものであり、他のコンポーネントから import するものではありません。
---

**重大度:** info · **カテゴリ:** architecture

## チェック内容

SvelteKit のルートエントリ —— `+page.svelte`、`+layout.svelte`、`+error.svelte`、およびそれらの `@`
分岐形式 —— を、別のコンポーネントから import している箇所を検出します。

## なぜ重要か

ルートエントリは、SvelteKit がそれを描画するという前提で書かれています。Kit はページに `data` と
`params` を渡し、エラーページには `page.error` と `page.status` を渡します。別の場所から import
すると、コンポーネントはそのどれも受け取れず、何もないまま描画されるか —— あるいは import
している側のページのデータを、自分のものであるかのように受け取って描画します。

この間違いは起こしやすく、一見もっともらしく見えます。別のページが同じマークアップを必要としていて、
そのマークアップはすでに `+page.svelte` の中にある —— だから import してしまう。他に異議を唱えるものは
何もなく、コンポーネントはそのまま描画されます —— 空のままで。

## 修正方法

共有したいマークアップを `$lib` 配下のコンポーネントとして切り出し、両方の場所からそれを import
してください。ルートエントリ自体は SvelteKit に任せます。

## 設定

| オプション | 型 | デフォルト |
| ----------------- | ------------- | ----------------------------------------------------------------- |
| `exemptImporters` | `string-list` | `['**/*.stories.svelte', '**/*.test.svelte', '**/*.spec.svelte']` |

`exemptImporters` にマッチするファイルは、ルートエントリを import してもかまいません。ストーリーは
それを見るために描画し、テストはそれに対してアサートするために描画し、どちらも SvelteKit が渡すはずの
ものを手で用意しています。

**このデフォルトは意図的に狭く、設定することは例外的な対応ではなく、想定された手順です。**
`string-list` のオプションはデフォルトに追加されるだけで、置き換えることはできません。つまりこの
リストを広げることはできても狭めることはできません —— だからこそ、エコシステム全体で共通する規約
だけをデフォルトとして持たせています。プロジェクトが別の方法でサテライトファイルを示している
場合は、自分のパターンを追加してください。

```js
// svelte-vitals.config.js
export default {
rules: {
'architecture/route-component-import': {
options: { exemptImporters: ['**/*.fixture.svelte'] }
}
}
};
```

## 報告されないもの

- ルートエントリへの動的 `import()`。import 宣言ではないため、アナライザーは検出しません。
- 素の `.ts` / `.js` ファイル、または `.svelte.ts` / `.svelte.js` モジュールからの import。import
に関する事実は `.svelte` コンポーネントファイルからのみ収集します。
- 型のみの import(`import type P from './+page.svelte'`、またはすべての指定子がインラインで型
指定されているもの)。ビルド時に消えるため、何も描画されません。
- ルートが `src/routes` 以外の場所にあるプロジェクト。
29 changes: 14 additions & 15 deletions docs/src/content/docs/ja/rules/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,20 @@ svelte-vitals が報告するルールをカテゴリ別にまとめました。

<CardGroup cols={2}>
<Card title="SEO" icon="search" href="/ja/rules/seo">
検索エンジンが実際に目にするもの。解決後の &lt;head&gt; メタデータ、構造化データ、クロールのしやすさを見ます。(31
件のルール)
検索エンジンが実際に目にするもの。解決後の &lt;head&gt; メタデータ、構造化データ、クロールのしやすさを見ます。
</Card>
<Card title="Performance" icon="zap" href="/ja/rules/performance">
ルートが遅くなる原因。画像、レンダリングを妨げるアセット、import、読み込みのウォーターフォールを見ます。(14
件のルール)
ルートが遅くなる原因。画像、レンダリングを妨げるアセット、import、読み込みのウォーターフォールを見ます。
</Card>
<Card title="Correctness" icon="circle-check" href="/ja/rules/correctness">
コンパイルは通るのに、思ったとおりに動かないコード。runes とライフサイクルの使い方を見ます。(14 件のルール)
コンパイルは通るのに、思ったとおりに動かないコード。runes とライフサイクルの使い方を見ます。
</Card>
<Card title="Security" icon="shield" href="/ja/rules/security">
エスケープされない HTML、安全でない URL、サーバーでリクエストをまたいで漏れる状態を見ます。(5 件のルール)
エスケープされない HTML、安全でない URL、サーバーでリクエストをまたいで漏れる状態を見ます。
</Card>
<Card title="Architecture" icon="layers" href="/ja/rules/architecture">
コードの形と置き場所のサイン。コンポーネントの大きさ、props の数、そしてプロジェクトが宣言した import
の境界を見ます。(6 件のルール)
の境界を見ます。
</Card>
</CardGroup>

Expand Down Expand Up @@ -116,13 +114,14 @@ svelte-vitals が報告するルールをカテゴリ別にまとめました。

## Architecture

| ルール | 重大度 | 概要 |
| ------------------------------------------------------------------------------------------ | ------- | ---------------------------------------------------------------------------------- |
| [`architecture/component-size`](/ja/rules/architecture/component-size) | 🔵 info | 大きくなりすぎたコンポーネントは分割しましょう。 |
| [`architecture/directory-naming`](/ja/rules/architecture/directory-naming) | 🔵 info | ディレクトリは、その場所に宣言した記法で名付けるべきです。 |
| [`architecture/private-scope-import`](/ja/rules/architecture/private-scope-import) | 🔵 info | プライベートなディレクトリ内のユニットを、その外から import すべきではありません。 |
| [`architecture/prop-count`](/ja/rules/architecture/prop-count) | 🔵 info | props が多すぎるコンポーネントは、担っている責務も多すぎます。 |
| [`architecture/reserved-directory-names`](/ja/rules/architecture/reserved-directory-names) | 🔵 info | ディレクトリの直下に置ける名前は、その位置に宣言した名前だけにすべきです。 |
| [`architecture/unit-entry-file`](/ja/rules/architecture/unit-entry-file) | 🔵 info | ユニットとして宣言したディレクトリには、同名のファイルを置くべきです。 |
| ルール | 重大度 | 概要 |
| ------------------------------------------------------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------- |
| [`architecture/component-size`](/ja/rules/architecture/component-size) | 🔵 info | 大きくなりすぎたコンポーネントは分割しましょう。 |
| [`architecture/directory-naming`](/ja/rules/architecture/directory-naming) | 🔵 info | ディレクトリは、その場所に宣言した記法で名付けるべきです。 |
| [`architecture/private-scope-import`](/ja/rules/architecture/private-scope-import) | 🔵 info | プライベートなディレクトリ内のユニットを、その外から import すべきではありません。 |
| [`architecture/prop-count`](/ja/rules/architecture/prop-count) | 🔵 info | props が多すぎるコンポーネントは、担っている責務も多すぎます。 |
| [`architecture/reserved-directory-names`](/ja/rules/architecture/reserved-directory-names) | 🔵 info | ディレクトリの直下に置ける名前は、その位置に宣言した名前だけにすべきです。 |
| [`architecture/route-component-import`](/ja/rules/architecture/route-component-import) | 🔵 info | SvelteKit のルートエントリはフレームワークが描画するものであり、他のコンポーネントから import するものではありません。 |
| [`architecture/unit-entry-file`](/ja/rules/architecture/unit-entry-file) | 🔵 info | ユニットとして宣言したディレクトリには、同名のファイルを置くべきです。 |

{/* rules-index:end */}
Loading