Last active
September 18, 2024 19:12
-
-
Save jacob-ebey/3a37a86307de9ef22f47aae2e593b56f to your computer and use it in GitHub Desktop.
Revisions
-
jacob-ebey revised this gist
Jan 5, 2022 . 1 changed file with 7 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -40,10 +40,17 @@ export let loader: LoaderFunction = async ({ request }) => { return badImageResponse(); } let width = getIntOrNull(url.searchParams.get("width")); let height = getIntOrNull(url.searchParams.get("height")); let fit: any = url.searchParams.get("fit") || "cover"; let hash = createHash("sha256"); hash.update("v1"); hash.update(request.method); hash.update(request.url); hash.update(width?.toString() || "0"); hash.update(height?.toString() || "0"); hash.update(fit); let key = hash.digest("hex"); let cachedFile = path.resolve(path.join(".cache/images", key + ".webp")); @@ -95,9 +102,6 @@ export let loader: LoaderFunction = async ({ request }) => { console.error(error); }); if (width || height) { sharpInstance.resize(width, height, { fit }); } -
jacob-ebey revised this gist
Jan 4, 2022 . 1 changed file with 19 additions and 17 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -17,6 +17,7 @@ function badImageResponse() { return new Response(buffer, { status: 500, headers: { "Cache-Control": "max-age=0", "Content-Type": "image/gif;base64", "Content-Length": buffer.length.toFixed(0), }, @@ -40,6 +41,7 @@ export let loader: LoaderFunction = async ({ request }) => { } let hash = createHash("sha256"); hash.update("v1"); hash.update(request.method); hash.update(request.url); let key = hash.digest("hex"); @@ -52,22 +54,17 @@ export let loader: LoaderFunction = async ({ request }) => { .catch(() => false); if (exists) { let fileStream = fs.createReadStream(cachedFile); return new NodeResponse(fileStream, { status: 200, headers: { "Content-Type": "image/webp", "Cache-Control": "public, max-age=31536000, immutable", }, }) as unknown as Response; } else { console.info("cache skipped for", src); } } catch (error) { console.error(error); @@ -77,16 +74,13 @@ export let loader: LoaderFunction = async ({ request }) => { let imageBody: Readable | undefined; let status = 200; if (src.startsWith("/") && (src.length === 1 || src[1] !== "/")) { imageBody = fs.createReadStream(path.resolve("public", src.slice(1))); } else { let imgRequest = new Request(src.toString()) as unknown as NodeRequest; imgRequest.agent = new https.Agent({ rejectUnauthorized: false, }); let imageResponse = await fetch(imgRequest as unknown as Request); imageBody = imageResponse.body as unknown as PassThrough; status = imageResponse.status; @@ -107,22 +101,30 @@ export let loader: LoaderFunction = async ({ request }) => { if (width || height) { sharpInstance.resize(width, height, { fit }); } sharpInstance.webp({ reductionEffort: 6 }); let imageManipulationStream = imageBody.pipe(sharpInstance); await fsp .mkdir(path.dirname(cachedFile), { recursive: true }) .catch(() => {}); let cacheFileStream = fs.createWriteStream(cachedFile); await new Promise<void>((resolve, reject) => { imageManipulationStream.pipe(cacheFileStream); imageManipulationStream.on("end", () => { resolve(); imageBody!.destroy(); }); imageManipulationStream.on("error", async (error) => { imageBody!.destroy(); await fsp.rm(cachedFile).catch(() => {}); }); }); let fileStream = fs.createReadStream(cachedFile); return new NodeResponse(fileStream, { status: status, headers: { "Content-Type": "image/webp", -
jacob-ebey revised this gist
Dec 31, 2021 . No changes.There are no files selected for viewing
-
jacob-ebey created this gist
Dec 31, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,136 @@ import { createHash } from "crypto"; import fs from "fs"; import fsp from "fs/promises"; import path from "path"; import https from "https"; import { PassThrough } from "stream"; import type { Readable } from "stream"; import type { LoaderFunction } from "remix"; import sharp from "sharp"; import type { Request as NodeRequest } from "@remix-run/node"; import { Response as NodeResponse } from "@remix-run/node"; let badImageBase64 = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; function badImageResponse() { let buffer = Buffer.from(badImageBase64, "base64"); return new Response(buffer, { status: 500, headers: { "Content-Type": "image/gif;base64", "Content-Length": buffer.length.toFixed(0), }, }); } function getIntOrNull(value: string | null) { if (value === null) { return null; } return Number.parseInt(value); } export let loader: LoaderFunction = async ({ request }) => { let url = new URL(request.url); let src = url.searchParams.get("src"); if (!src) { return badImageResponse(); } let hash = createHash("sha256"); hash.update(request.method); hash.update(request.url); let key = hash.digest("hex"); let cachedFile = path.resolve(path.join(".cache/images", key + ".webp")); try { let exists = await fsp .stat(cachedFile) .then((s) => s.isFile()) .catch(() => false); if (exists) { let responseBody = new PassThrough(); let fileStream = fs.createReadStream(cachedFile); fileStream.pipe(responseBody).on("end", () => { fileStream.destroy(); }); return new NodeResponse(responseBody, { status: 200, headers: { "Content-Type": "image/webp", "Cache-Control": "public, max-age=31536000, immutable", }, }) as unknown as Response; } else { console.log("cache skipped for", src); } } catch (error) { console.error(error); } try { let imageBody: Readable | undefined; let status = 200; if (src.startsWith("/")) { imageBody = fs.createReadStream(path.resolve("public", src.slice(1))); } else { let imgRequest = new Request(src.toString()) as unknown as NodeRequest; imgRequest.agent = new https.Agent({ rejectUnauthorized: false, }); if (imgRequest.url.startsWith("http://")) { console.log({ "imgRequest.url": imgRequest.url }); } let imageResponse = await fetch(imgRequest as unknown as Request); imageBody = imageResponse.body as unknown as PassThrough; status = imageResponse.status; } if (!imageBody) { return badImageResponse(); } let sharpInstance = sharp(); sharpInstance.on("error", (error) => { console.error(error); }); let width = getIntOrNull(url.searchParams.get("width")); let height = getIntOrNull(url.searchParams.get("height")); let fit: any = url.searchParams.get("fit") || "cover"; if (width || height) { sharpInstance.resize(width, height, { fit }); } sharpInstance.webp({ lossless: true }); let responseBody = new PassThrough(); let imageManipulationStream = imageBody.pipe(sharpInstance); await fsp .mkdir(path.dirname(cachedFile), { recursive: true }) .catch(() => {}); let cacheFileStream = fs.createWriteStream(cachedFile); imageManipulationStream.pipe(cacheFileStream); imageManipulationStream.pipe(responseBody).on("end", () => { imageBody!.destroy(); }); return new NodeResponse(responseBody, { status: status, headers: { "Content-Type": "image/webp", "Cache-Control": "public, max-age=31536000, immutable", }, }) as unknown as Response; } catch (error) { console.error(error); return badImageResponse(); } }; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,56 @@ import type { ComponentPropsWithoutRef } from "react"; export function OptimizedImage({ optimizerUrl = "/resources/image", responsive, src, ...rest }: ComponentPropsWithoutRef<"img"> & { optimizerUrl?: string; responsive?: { maxWidth?: number; size: { width: number; height?: number }; }[]; }) { let url = src ? optimizerUrl + "?src=" + encodeURIComponent(src) : src; let props: ComponentPropsWithoutRef<"img"> = { src: url + `&width=${rest.width || ""}&height=${rest.height || ""}`, }; let largestImageWidth = 0; let largestImageSrc: string | undefined; if (responsive && responsive.length) { let srcSet = ""; let sizes = ""; for (let { maxWidth, size } of responsive) { if (srcSet) { srcSet += ", "; } let srcSetUrl = url + `&width=${size.width}&height=${size.height || ""} ${size.width}w`; srcSet += srcSetUrl; if (maxWidth) { if (sizes) { sizes += ", "; } sizes += `(max-width: ${maxWidth}px) ${size.width}px`; } if (size.width > largestImageWidth) { largestImageWidth = size.width; largestImageSrc = srcSetUrl; } } props.srcSet = srcSet; props.sizes = sizes; props.src = ""; } if (largestImageSrc && (!rest.width || largestImageWidth > rest.width)) { props.src = largestImageSrc; } return <img {...rest} {...props} />; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,30 @@ <OptimizedImage loading={index === 0 ? "eager" : "lazy"} className="w-full h-full object-contain" src={image} alt="" height={480} width={480} responsive={[ { size: { height: 480, width: 480, }, maxWidth: 600, }, { size: { height: 767, width: 767, }, maxWidth: 767, }, { size: { height: 1024, width: 1024, }, }, ]} />