Cloudflare PagesとAstroでURL短縮サービスを構築する
AI生成の要約
この記事では、Cloudflare PagesとAstroを使用してURL短縮サービスを構築する方法を紹介します。この記事では、環境設定、AstroとCloudflareの統合、Cloudflare KVの設定、ページの実装とデプロイについて説明します。これらの手順に従うことで、完全に機能するURL短縮サービスを構築することができます。
Prerequisite
- Docker
- VSCode
- Cloudflareアカウント
環境設定
VSCodeの開発コンテナを使用します
VSCodeでF1を押します
Dev Containers: Add Dev Container Configuration Files...を選択します
node.js環境を選択します:

以下は私が使用したdevcontainer.jsonとDockerfileです
{
"name": "Untitled Node.js project",
"build": {
"dockerfile": "Dockerfile"
},
"remoteUser": "node",
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {}
},
"forwardPorts": [
4321, // for astro dev server
8976 // for wrangler login
],
"customizations": {
"vscode": {
"extensions": [
"astro-build.astro-vscode",
"svelte.svelte-vscode",
"dbaeumer.vscode-eslint",
"GitHub.copilot",
"GitHub.copilot-chat"
]
}
}
}forwardPortsは後で開発のために必要です
FROM node:22
# Install basic development tools
RUN apt update && apt install -y less man-db sudo
# Ensure default `node` user has access to `sudo`
ARG USERNAME=node
RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
# Set `DEVCONTAINER` environment variable to help with orientation
ENV DEVCONTAINER=true他のVSCode開発コンテナについては、別の記事を参照してください
Astroの設定
コンテナに入った後、公式ツールを使用してAstroファイルを生成します
npm create astro@latest
# dir Where should we create your new project?
# ./astro
# tmpl How would you like to start your new project?
# A basic, minimal starter
# deps Install dependencies?
# Yes
# git Initialize a new git repository?
# Yes生成されたファイルは/astroフォルダにあります。すべての内容を移動しました
mv astro/* .
rm -rf astro開発サーバーを起動してみて、初期画面が表示されるはずです
npm run dev
Cloudflare Integration
Cloudflare Integrationを追加します
npx astro add cloudflare自動的にファイルを設定してくれるはずですが、いくつかの設定を追加する必要があります:
export default defineConfig({
output: "server",
adapter: cloudflare({
platformProxy: {
enabled: true,
},
}),
})このURL短縮サービスは純粋な静的ウェブサイトではないので、AstroがデフォルトでSSRを使用するようにoutput: 'server'を設定します
platformProxy.enabledは、ローカルでCloudflareの機能を使用できるようにするためのものです
詳細については、公式ドキュメントを参照してください
Cloudflare KVの設定
こののURL短縮サービスは、短縮URLとキー値ペアを保存する必要があります。ここではCloudflare KVを使用します
wranglerにログイン
wranglerはCloudflareの公式ツールです。まずログインしましょう
npx wrangler loginブラウザがポップアップするはずですが、開発コンテナでは自動的にポップアップしないため、手動でURLをコピーしてブラウザに貼り付ける必要があります

同意すると、ページはポート8976にリダイレクトしようとしますが、失敗するかもしれません
しかし、devcontainer.jsonでこのポートを開いているので、正常にログインできるはずです
KV Namespaceの作成
データを保存するための名前空間を作成し、SHORT_TO_URLと名付けます
npx wrangler@latest kv:namespace create SHORT_TO_URLターミナルからIDを取得し、wrangler.tomlに追加します
[[kv_namespaces]]
binding = "SHORT_TO_URL"
id = "[YOUR ID HERE]"開発環境がSHORT_TO_URLを認識するようにするために、env.d.tsを追加します
/// <reference types="astro/client" />
type KVNamespace = import("@cloudflare/workers-types").KVNamespace;
type ENV = {
SHORT_TO_URL: KVNamespace;
};
// use a default runtime configuration (advanced mode).
type Runtime = import("@astrojs/cloudflare").Runtime<ENV>;
declare namespace App {
interface Locals extends Runtime {}
}詳細については、公式ドキュメントを参照してください
.wranglerフォルダが表示されましたが、バージョン管理に追加する必要はないようですので、.gitignoreに追加します:
.wrangler/ページの実装
3つのエンドポイントを用意します:
src/pages/index.astro- ホームページ。静的で、ユーザーがURLを入力して送信するためのフォームを準備します
src/pages/shorten.ts- URLを受け取り、短縮されたslugを返します
src/pages/[slug].ts- slugを受け取り、保存されたURLにリダイレクトします
src/pages/index.astro
このページは基本的にインタラクティブなフォームが必要で、SSRは必要ありません。prerender = trueを追加して指定します
こちらを参照してください
---
export const prerender = true;
---フォームの実装にはSvelteを使用します
npx astro add svelteCSS部分は省略しますが、index.astroでは、コンポーネントをインタラクティブにするためにclient:loadとして指定する必要があります
<Form client:load />フォームの内容は通常のフロントエンド実装と同じです。GitHubを参照してください
src/pages/shorten.ts
このエンドポイントはURLを受け取り、短縮されたslugを返すために使用されます
md5暗号化を使用するので、まずパッケージをインストールします:
npm i -S js-md5slugを計算した後、localsから以前に設定したSHORT_TO_URLを取得できます
import type { APIRoute } from "astro"
import { md5 } from "js-md5"
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
export const POST: APIRoute = async ({ request, locals }) => {
try {
const body = await request.json()
const url = new URL(body.url)
let hashed = Number.parseInt(md5.hex(url.href), 16)
let slug = ""
for (let i = 0; i < 6; i++) {
slug += charset[hashed % charset.length]
hashed = Math.floor(hashed / charset.length)
}
const { SHORT_TO_URL } = locals.runtime.env
await SHORT_TO_URL.put(slug, url.href)
return new Response(JSON.stringify({ slug }))
}
catch (e) {
return new Response(JSON.stringify({ error: "Invalid URL" }), { status: 400 })
}
}src/pages/[slug].ts
このエンドポイントは受け取ったslugを処理し、以前に保存されたURLをクエリしてリダイレクトを提供する必要があります
import type { APIRoute } from "astro"
export const GET: APIRoute = async ({ params, locals, redirect }) => {
const slug: string = params.slug ?? ""
const { SHORT_TO_URL } = locals.runtime.env
const url = await SHORT_TO_URL.get(slug)
if (!url) {
return new Response(JSON.stringify({ error: "Not found" }), { status: 404 })
}
return redirect(url, 301)
}デプロイ
package.jsonにビルドとデプロイコマンドを設定できます
{
"scripts": {
// ...
"deploy": "astro build && wrangler pages deploy",
}
}npm run deploy成功!しかし、私のドメイン名は長すぎて、全く短縮されませんでした 🙃

疑問
最初はCloudflare Pagesに含まれるデプロイ機能を使用するように設定しましたが、この機能だけを使用するとワーカーが自動的に生成されません。 つまり、静的ページのみが正常にデプロイされ(他のページは404が表示されます)
ローカルからwrangler pages deployを使用するだけでうまくいくようです