コンテンツは変わります(必ず変わります)。リダイレクト は、利用者と(友好的な)ボットの連続性を保ちます。
いちばん分かりやすいのはユーザー体験です。ダッシュボードのリンクをクリックしたり、ブックマークした URL を使ったりするとき、正しい場所へ行くと信頼しています。404 ページでも誤ったページでもなく、正しいページです。リダイレクトは、利用者を正しい場所へ案内します。
自動化された体験でも同じです。リダイレクトなしでページを移すと、Google などの検索エンジンがページを順位付けするときに使う、過去の検索オーソリティを失います。
第一の方法は Workers Static Assets を使い、GitHub リポジトリの プレーンテキストファイル ↗ にリダイレクトを定義します。
この構成では、リダイレクトもほかのドキュメント変更と同じワークフローで扱えます。コンテンツ変更と同じプルリクエストでリダイレクトを入れ、プレビューブランチで確認できます。メンテナンスでは、リダイレクトを製品ごとに 整理 し、各製品内ではアルファベット順にします。
Pages の構文 が持つ柔軟性も活用しています。
状況によっては Bulk redirects も使います。この方法は控えめに使います。リダイレクトが複数箇所にあると、変更時の認知負荷と混乱が増えるためです。
通常、Bulk redirects が出てくるのは、別チームがサイトへ個別リダイレクトを大量に追加するときです。たとえば、以前の support.cloudflare.com のコンテンツを移行し、ロケールごとに個別のリダイレクトが必要だったときです。
コントリビューターがチーム外であり、リダイレクト件数が多く __redirects ファイルが煩雑になり リダイレクトの上限 に抵触しそうなときに、この方法を使います。
チームがリダイレクトを追加するのは 2 つの場面です。通常のコンテンツ作業の過程と、データに基づいて必要なときです。
通常のコンテンツ作業では、ページに次をしたときにリダイレクトを追加します。
- URL の一部(ファイル名、フォルダー)を変更した。
- ページを削除した。
必要なリダイレクトを知らせる 自動化もあります。
ドキュメントサイトの特定パスで 404 レスポンスコードが多いときも、リダイレクトを追加します。こうした 404 は、リダイレクト漏れや誤ったリンクが原因のことがあります。
これらのステータスコードは、Cloudflare analytics(随時)または Logpush ジョブ(より詳細、四半期ごと)で把握します。
リダイレクト向けに、GitHub 上で 2 つの自動化を動かしています。
無限リダイレクトは、2 つのページが互いにリダイレクトし続け、利用者がブラウザーをクラッシュさせる無限ループに入る状態です。
体験として非常に悪いため、必須の CI GitHub action ↗ で明示的に検査します。
この検査はサイトのビルド 後 に実行します。そのうえで validate-redirects.ts ↗ を呼び出し、次があると失敗します。
- 無限リダイレクト
- 重複したリダイレクト
- アンカーリンクを含むリダイレクト先
validate-redirects.ts
import { readFile } from "fs/promises";
async function main() {
const redirects = await readFile("public/__redirects", { encoding: "utf-8" });
let numInfiniteRedirects = 0;
let numUrlsWithFragment = 0;
let numDuplicateRedirects = 0;
const redirectSourceUrls: string[] = [];
for (const line of redirects.split("\n")) {
if (line.startsWith("#") || line.trim() === "") continue;
const [from, to] = line.split(" ");
if (from === to) {
console.log(`✘ Found infinite redirect:\n ${from} -> ${to}`);
numInfiniteRedirects++;
}
if (from.includes("#")) {
console.log(`✘ Found source URL with fragment:\n ${from}`);
numUrlsWithFragment++;
}
if (redirectSourceUrls.includes(from)) {
console.log(`✘ Found repeated source URL:\n ${from}`);
numDuplicateRedirects++;
} else {
redirectSourceUrls.push(from);
}
}
if (numInfiniteRedirects || numUrlsWithFragment || numDuplicateRedirects) {
console.log("\nDetected errors:");
if (numInfiniteRedirects > 0) {
console.log(`- ${numInfiniteRedirects} infinite redirect(s)`);
}
if (numUrlsWithFragment > 0) {
console.log(`- ${numUrlsWithFragment} source URL(s) with a fragment`);
}
if (numDuplicateRedirects > 0) {
console.log(`- ${numDuplicateRedirects} repeated source URL(s)`);
}
console.log("\nPlease fix the errors above before merging :)");
process.exit(1);
} else {
console.log("\nDone!");
}
}
main();コントリビューターは、いつリダイレクトを追加すべきか判断に迷うことがよくあります。コンテンツファイルのパスを変更または削除するプルリクエストに コメントを付ける ↗ ことで、判断を助けています。
できる限り、リダイレクトを論理的なグループ(製品、アルファベット順)にまとめます。重複リダイレクトを防ぎ、探している特定のリダイレクトも見つけやすくなります。
__redirects ファイル ↗ では、コメントを多用し、製品領域ごとに区切っています。各セクション内では、できる限りアルファベット順にしています。
以前は(それが第一の方法だったころ)、Bulk Redirect リスト にも同じ考え方を当てはめていました。似た製品をまとめたリストを作り、そのようにラベルを付けて、探しているリダイレクトを見つけやすくしていました。
サーバーレベルでは、URL パス(/page/)ではリダイレクトを起こせますが、フラグメント(/page/#fragment)では起こせません。
ページからフラグメントへリダイレクトすることはできます(/page1/ から /page2/#fragment)。
可能なら、リダイレクトを連鎖させず、利用者を目的地へ直接送ります。
そうしないと、次のような状態になります。
Page 1 --Redirect-> Page 2 --Redirect-> Page 3 --Redirect-> Page 4リダイレクトチェーンがよくない理由は次のとおりです。
- ユーザー体験が遅くなります。
- 意図しない結果(無限リダイレクト、リダイレクト漏れ、誤ったリダイレクト)が起きやすくなります。
これを避けるには、以前のリダイレクトの宛先を継続的に更新します。たとえば、このページの名前を /style-guide/how-we-docs/redirect-guidance/ に変えたとします。
リダイレクトファイルを更新するプルリクエストでは、既存のリダイレクトも更新し、新しいリダイレクトも追加します。
- /style-guide/redirects/ /style-guide/how-we-docs/redirects/ 301
+ /style-guide/redirects/ /style-guide/how-we-docs/redirect-guidance/ 301
+ /style-guide/how-we-docs/redirects/ /style-guide/how-we-docs/redirect-guidance/ 301