SEO で最も重要なのは、高品質なコンテンツを作ること、そしてそれが web 上で広くリンクされることです。しかし、ランクが高いサイトを構築するためにいくつか技術的に考慮すべきこともあります。
## Out of the box
### SSR
近年、検索エンジンはクライアントサイドの JavaScript でレンダリングされたコンテンツのインデックスを改善してきましたが、サーバーサイドレンダリングされたコンテンツのほうがより頻繁に、より確実にインデックスされます。SvelteKit はデフォルトで SSR を採用しています。[`handle`](hooks#Server-hooks-handle) で無効にすることもできますが、適切な理由がない場合はそのままにしておきましょう。
> [!NOTE] SvelteKit のレンダリングは高度な設定が可能です。必要であれば、[動的なレンダリング(dynamic rendering)](https://developers.google.com/search/docs/advanced/javascript/dynamic-rendering) を実装することも可能です。一般的には推奨されません、SSR には SEO 以外のメリットもあるからです。
### パフォーマンス
[Core Web Vitals](https://web.dev/vitals/#core-web-vitals) のような指標は検索エンジンのランクに影響を与えます。Svelte と SvelteKit はオーバーヘッドが最小限であるため、ハイパフォーマンスなサイトを簡単に構築できです。Google の [PageSpeed Insights](https://pagespeed.web.dev/) や [Lighthouse](https://developers.google.com/web/tools/lighthouse) で、ご自身のサイトをテストすることができます。詳細は [パフォーマンスのページ](performance) をお読みください。
### URLの正規化
SvelteKit は、末尾のスラッシュ(trailing slash)付きのパス名から、末尾のスラッシュが無いパス名にリダイレクトします ([設定](page-options#trailingSlash) で逆にできます)。URLの重複は、SEOに悪影響を与えます。
## Manual setup
### <title> と <meta>
全てのページで、よく練られたユニークな `
` と `` を [``](../svelte/svelte-head) の内側に置くべきです。説明的な title と description の書き方に関するガイダンスと、検索エンジンにとってわかりやすいコンテンツを作るためのその他の方法については、Google の [Lighthouse SEO audits](https://web.dev/lighthouse-seo/) のドキュメントで見つけることができます。
> [!NOTE] よくあるパターンとしては、ページの [`load`](load) 関数から SEO 関連の `data` を返し、それを最上位の[レイアウト](routing#layout)の `` で ([`page.data`]($app-state) として) 使用することです。
### サイトマップ
[サイトマップ](https://developers.google.com/search/docs/advanced/sitemaps/build-sitemap) は、検索エンジンがサイト内のページの優先順位付けをするのに役立ちます、特にコンテンツの量が多い場合は。エンドポイントを使用してサイトマップを動的に作成できます:
```js
/// file: src/routes/sitemap.xml/+server.js
export async function GET() {
return new Response(
`
`.trim(),
{
headers: {
'Content-Type': 'application/xml'
}
}
);
}
```
### AMP
現代の web 開発における不幸な現実として、サイトの [Accelerated Mobile Pages (AMP)](https://amp.dev/) バージョンを作らなければならないときがある、というのがあります。SvelteKit では、[`inlineStyleThreshold`](configuration#inlineStyleThreshold) オプションを設定することでこれを実現することができます…
```js
/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
// since isn't
// allowed, inline all styles
inlineStyleThreshold: Infinity
}
};
export default config;
```
…最上位(root)の `+layout.js`/`+layout.server.js` の `csr` を無効にします…
```js
/// file: src/routes/+layout.server.js
export const csr = false;
```
…`amp` を `app.html` に追加します
```html
...
```
…そして、`transformPageChunk` と、`@sveltejs/amp` からインポートできる `transform` を使用して、HTML を変換します:
```js
/// file: src/hooks.server.js
import * as amp from '@sveltejs/amp';
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
let buffer = '';
return await resolve(event, {
transformPageChunk: ({ html, done }) => {
buffer += html;
if (done) return amp.transform(buffer);
}
});
}
```
ページを amp に変換した結果として未使用の CSS が配布されてしまうのを防ぎたければ、[`dropcss`](https://www.npmjs.com/package/dropcss) を使用すると良いでしょう:
```js
// @filename: ambient.d.ts
declare module 'dropcss';
// @filename: index.js
// ---cut---
/// file: src/hooks.server.js
// @errors: 2307
import * as amp from '@sveltejs/amp';
import dropcss from 'dropcss';
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
let buffer = '';
return await resolve(event, {
transformPageChunk: ({ html, done }) => {
buffer += html;
if (done) {
let css = '';
const markup = amp
.transform(buffer)
.replace('⚡', 'amp') // dropcss can't handle this character
.replace(/`;
});
css = dropcss({ css, html: markup }).css;
return markup.replace('', `${css}`);
}
}
});
}
```
> [!NOTE] `amphtml-validator` を使用して変換された HTML を検証するのに、`handle` hook を利用するのは良いアイデアですが、非常に遅くなってしまうので、ページをプリレンダリングするときだけにしてください。