Open10

remixで写真投稿サイトを作る

GENYAGENYA

画像の保存先に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; // ここを追加

}

GENYAGENYA

画像リストの取得


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;
};
GENYAGENYA

画像むけのアクセスパスを作成

// 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 });
};

GENYAGENYA

画像むけのアクセスパスを作成

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>
  );
}


GENYAGENYA

画像ファイルのキャッシュ追加

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;
});


GENYAGENYA

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",
});