Skip to content
This repository was archived by the owner on Jan 14, 2026. It is now read-only.

Commit ee5e64e

Browse files
Add cache implementation for images
This PR adds a caching implementation for images hosted as part of the Sanity project for built-with.
1 parent 959de43 commit ee5e64e

File tree

4 files changed

+34
-6
lines changed

4 files changed

+34
-6
lines changed

app/components/project.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from "react"
22
import { Link } from "@remix-run/react"
3+
import { cacheableUrl } from "../utils"
34

45
import "../styles/project.css"
56

@@ -13,7 +14,7 @@ const Project = ({ isInitialRoute, project }) => {
1314
>
1415
<div className="Project Project-fills-height">
1516
<div className="Project--image">
16-
<img className="Project--image-img" src={project.image.asset.url} />
17+
<img className="Project--image-img" src={cacheableUrl(project.image.asset.url)} />
1718
</div>
1819

1920
<div className="Project--content">

app/routes/built-with.projects.$slug.jsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Link, useLoaderData } from "@remix-run/react"
55
import { json, redirect } from "@remix-run/cloudflare";
66
import { ClientOnly } from "remix-utils/client-only"
77

8+
import { cacheableUrl } from "../utils"
89
import { getSanityClient } from "../lib/sanity"
910
import Layout from "../components/layout"
1011
import Markdown from "../components/markdown"
@@ -29,10 +30,10 @@ export const meta = ({ data }) => {
2930
{ name: "description", content: shortDescription },
3031
{ name: "og:title", content: title },
3132
{ name: "og:description", content: shortDescription },
32-
{ name: "og:image", content: image.asset.url },
33+
{ name: "og:image", content: cacheableUrl(image.asset.url) },
3334
{ name: "twitter:title", content: title },
3435
{ name: "twitter:description", content: shortDescription },
35-
{ name: "twitter:image:src", content: image.asset.url }
36+
{ name: "twitter:image:src", content: cacheableUrl(image.asset.url) }
3637
];
3738
};
3839

@@ -146,11 +147,11 @@ const Project = () => {
146147
<Stream
147148
controls src={project.stream_video_id}
148149
letterboxColor="transparent"
149-
poster={project.image.asset.url}
150+
poster={cacheableUrl(project.image.asset.url)}
150151
/>
151152
) : (
152153
<img
153-
src={project.image.asset.url}
154+
src={cacheableUrl(project.image.asset.url)}
154155
style={{ objectFit: "cover", width: "100%" }}
155156
/>
156157
)}

app/utils.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,14 @@ const sortProjects = (collection) => {
148148
return projects;
149149
}
150150

151+
// Take a Sanity asset image url and return a relative path that is cached by CF
152+
const cacheableUrl = u => {
153+
return `/api/v1/image-proxy?url=${encodeURIComponent(u.toString())}`
154+
}
155+
151156
export {
152157
PROJECTS_PER_COLLECTION,
158+
cacheableUrl,
153159
flatten,
154160
normalizeCollection,
155161
resultTemplate,

server.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,26 @@ export default {
3636
}
3737
}
3838

39+
if (url.pathname.startsWith("/api/v1/image-proxy")) {
40+
const url = new URL(request.url)
41+
const originalUrl = url.searchParams.get("url")
42+
if (!originalUrl) {
43+
return new Response("Missing url", { status: 400 })
44+
}
45+
46+
let cache = caches.default
47+
const cacheKey = originalUrl
48+
const cachedResponse = await cache.match(cacheKey)
49+
if (cachedResponse) {
50+
return cachedResponse
51+
}
52+
53+
const response = await fetch(originalUrl, request)
54+
cache.put(cacheKey, response.clone())
55+
return response
56+
}
57+
58+
3959
// Handle with Remix
4060
try {
4161
const loadContext = {
@@ -61,4 +81,4 @@ export default {
6181
return new Response(error.toString(), { status: 500 });
6282
}
6383
},
64-
};
84+
};

0 commit comments

Comments
 (0)