serveAsset
uses node:path
Serve an asset of the shared directory: immutable (its name is its content), compressed as the browser accepts.
A chunk is offered as a dictionary for the next version of it (Use-As-Dictionary), and a browser that has the
previous version (Available-Dictionary) gets the new one as the difference (dcb): a deploy that changes a
chunk a little costs the browser a little.
import { acceptedEncodings, chunkStem, CONTENT_TYPES, delta, digestOf } from "#codebase/tcmts/cli/web"; import fs from "node:fs"; import type http from "node:http"; import path from "node:path"; export function serveAsset( req: http.IncomingMessage, res: http.ServerResponse, file: string, base = "", ) { const accepts = acceptedEncodings(req); const chunk = chunkStem(file); const dir = path.dirname(file); let sent = file; let encoding: string | undefined; const wanted = /^:([A-Za-z0-9+/=]+):$/.exec( String(req.headers["available-dictionary"] ?? "").trim(), )?.[1]; if (chunk && wanted && accepts.has("dcb")) { const dictionary = fs .readdirSync(dir) .find( (f) => f !== path.basename(file) && chunkStem(f)?.stem === chunk.stem && chunkStem(f)?.ext === chunk.ext && digestOf(path.join(dir, f)) === wanted, ); const d = dictionary && delta(file, path.join(dir, dictionary), path.join(dir, "..", "deltas")); if (d) [sent, encoding] = [d, "dcb"]; } if (!encoding) { const e = (["br", "gzip"] as const).find( (x) => accepts.has(x) && fs.existsSync(`${file}.${x === "br" ? "br" : "gz"}`), ); if (e) [sent, encoding] = [`${file}.${e === "br" ? "br" : "gz"}`, e]; } res.statusCode = 200; res.setHeader("content-type", CONTENT_TYPES[path.extname(file)] ?? "application/octet-stream"); res.setHeader("cache-control", "public, max-age=31536000, immutable"); res.setHeader("vary", chunk ? "Accept-Encoding, Available-Dictionary" : "Accept-Encoding"); if (chunk) res.setHeader("use-as-dictionary", `match="${base}/_app/assets/${chunk.stem}-*${chunk.ext}"`); if (encoding) res.setHeader("content-encoding", encoding); res.setHeader("content-length", fs.statSync(sent).size); if (req.method === "HEAD") return res.end(); fs.createReadStream(sent).pipe(res); }
uses
- tcmts.cli.web.CONTENT_TYPES
- tcmts.cli.web.acceptedEncodings
- tcmts.cli.web.chunkStem
- tcmts.cli.web.delta
- tcmts.cli.web.digestOf