testDeployedChunksArriveAsDifferences
After a deploy, a browser that has the app's previous chunk gets the new one as the difference from it
(Compression Dictionary Transport): Chrome asks with the old chunk's hash, and the server sends dcb, a few
hundred bytes for a chunk of thousands.
import { CHROME, withPage } from "#codebase/tcmts/cli/test/browser"; import { plainEnv, tcmBin, withChildren } from "#codebase/tcmts/cli/test/e2e/harness"; import { setUp, waitFor } from "#codebase/tcmts/cli/test/e2e/prod"; import assert from "node:assert/strict"; import { spawn } from "node:child_process"; import type { ChildProcess } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; export const testDeployedChunksArriveAsDifferences = () => withChildren(async (keep) => { if (!CHROME) return console.log("skipped: no Chrome"); const { dir, tcm, scratch } = setUp(); // browser code with some bulk to it, so the difference is worth sending const app = (version: string) => `// tcm: namespace app\n` + `export const words = (): string[] => Array.from({ length: 200 }, (_, i) => "word" + i + ["alpha", "beta", "gamma"][i % 3]);\n` + `export const describe = (n: number): string => n > 100 ? "many " + words().slice(0, 3).join(", ") : "few";\n` + `export function main() { document.querySelector("#app")!.textContent = "${version} " + describe(words().length); }\n`; scratch(app("v1")); tcm("add"); tcm("build", "app.main"); const child: ChildProcess = keep( spawn(process.execPath, [tcmBin(), "start", "app.main", "--port", "0"], { cwd: dir, env: plainEnv(), }), ); let out = ""; child.stdout!.setEncoding("utf8").on("data", (d: string) => (out += d)); child.stderr!.setEncoding("utf8").on("data", (d: string) => (out += d)); await waitFor(() => /url\s+http:\/\/\S+/.test(out)); const url = /url\s+(http:\/\/\S+)/.exec(out)![1]!; await withPage(url, async (p) => { assert.match( await p.waitFor<string>(`document.querySelector("#app")?.textContent ?? ""`, (t) => t.startsWith("v1"), ), /^v1 many/, ); scratch(app("v2")); tcm("update"); await waitFor(() => /deployed app\.main/.test(out)); await p.evaluate("location.reload()"); assert.match( await p.waitFor<string>(`document.querySelector("#app")?.textContent ?? ""`, (t) => t.startsWith("v2"), ), /^v2 many/, ); assert.deepEqual(p.errors, []); // what Chrome received for the app's new chunk const sizes = await p.evaluate<{ name: string; encoded: number; decoded: number }[]>( `performance.getEntriesByType("resource").filter((e) => e.name.includes("/_app/assets/app-")).map((e) => ({ name: e.name, encoded: e.encodedBodySize, decoded: e.decodedBodySize }))`, ); const deltas = path.join(dir, ".tcm", "apps", "deltas"); const made = fs.existsSync(deltas) ? fs.readdirSync(deltas).filter((f) => f.endsWith(".dcb")) : []; assert.equal(made.length, 1, `the server made the difference once: ${made.join(", ")}`); const [newer] = sizes.slice(-1); assert.ok( newer && newer.encoded > 0 && newer.encoded === fs.statSync(path.join(deltas, made[0]!)).size, JSON.stringify(sizes), ); const br = fs.statSync( path.join( dir, ".tcm", "apps", "assets", `${path.basename(new URL(newer.name).pathname)}.br`, ), ).size; assert.ok( newer.encoded < br / 2, `the difference (${newer.encoded} bytes) is much less than the chunk (${br} bytes, compressed)`, ); }); })