Open10
remixで写真投稿サイトを作る
まずはremix init
npx create-remix@latest
画像の保存先にr2の設定追加
wrangler.toml
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "photo-base"
preview_bucket_name = "photo-base"
types/bindings.d.ts
declare global {
const __STATIC_CONTENT: KVNamespace;
const SESSION_SECRET: string;
const MY_BUCKET: R2Bucket; // ここを追加
}
画像リストの取得
export const loader: LoaderFunction = async () => {
const list = await MY_BUCKET.list();
if (!list || !list.objects) return [];
const filtered = list.objects.filter(
(obj) => obj.httpMetadata.contentType === "image/jpeg"
);
return filtered;
};
画像むけのアクセスパスを作成
// app/routes/$key.tsx
import { json } from "@remix-run/cloudflare";
import type { LoaderFunction } from "@remix-run/cloudflare";
export const loader: LoaderFunction = async ({ params }) => {
const object = await MY_BUCKET.get(params.key);
if (object === null) {
return json({ message: "Object not found" }, { status: 404 });
}
const headers: HeadersInit = new Headers();
object.writeHttpMetadata(headers);
headers.set("etag", object.etag);
return new Response(object.body, { headers });
};
画像むけのアクセスパスを作成
html 部分の構築
// app/routes/index.tsx
export default function Index() {
const data = useLoaderData();
return (
<div>
{data.map((data) => {
return (
<img
src={`/${data.key}`}
key={data.key}
/>
);
})}
</div>
);
}
upload するページの作成
tailwind のインストールガイド
画像ファイルのキャッシュ追加
sw.jsの読み込み
// app/entry.client.tsx
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker.register("/sw.js");
});
}
sw.jsファイルの作成
// public/sw.js
self.addEventListener("fetch", (event) => {
let url = new URL(event.request.url);
let method = event.request.method;
if (method.toLowerCase() !== "get") return;
if (
url.pathname.endsWith("jpeg") ||
url.pathname.endsWith("jpg") ||
url.pathname.endsWith("png") ||
url.pathname.startsWith("/styles/")
) {
event.respondWith(
caches.open("assets").then(async (cache) => {
let cacheResponse = await cache.match(event.request);
if (cacheResponse) return cacheResponse;
let fetchResponse = await fetch(event.request);
cache.put(event.request, fetchResponse.clone());
return fetchResponse;
})
);
}
return;
});
OGPの追加
今回はトップのみなので全て固定の文字
// app/root.tsx
export const meta: MetaFunction = () => ({
charset: "utf-8",
title: "photo base by GENYA",
"og:title": `photo base by GENYA`,
viewport: "width=device-width,initial-scale=1",
description: "お気に入りの写真サイト",
"og:url": `https://photo-base.drill.dev/`,
"og:description": "お気に入りの写真サイト",
"og:image": `https://photo-base.drill.dev/40173124-e524-48c1-acc4-1750138e59ce.jpeg`,
"og:site_name": "photo base by GENYA",
"twitter:card": "summary_large_image",
"twitter:creator": "@genya2022",
"twitter:site": "@genya2022",
});
cf workers にデプロイ。