Skip to content

Commit bcdef26

Browse files
committed
Hash demo bundle filename to bypass Pages CDN cache
GitHub Pages serves with cache-control: max-age=600 which can't be overridden. That used to mean every deploy could take up to ten minutes to become visible to repeat visitors. Naming the rollup entry as bundle-[hash].js and rewriting examples/index.html to reference the freshly emitted filename sidesteps the cache entirely — each deploy yields a different URL for the asset and browsers re-fetch on first navigation. Also cleans up stale bundle-*.js from previous builds so docs/ doesn't accrete.
1 parent d89299b commit bcdef26

1 file changed

Lines changed: 25 additions & 5 deletions

File tree

rollup.config.demo.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,21 @@ import resolve from "@rollup/plugin-node-resolve"
1111
import commonjs from "@rollup/plugin-commonjs"
1212
import terser from "@rollup/plugin-terser"
1313
import {lezer} from "@lezer/generator/rollup"
14-
import {copyFileSync, mkdirSync} from "node:fs"
14+
import {mkdirSync, readFileSync, writeFileSync, readdirSync, rmSync} from "node:fs"
1515

1616
mkdirSync("docs", {recursive: true})
1717

18+
// Pages serves with cache-control: max-age=600, which means browsers and the
19+
// edge CDN keep serving the same `bundle.js` for ten minutes after a deploy.
20+
// Naming the entry with a content-hash sidesteps the cache entirely: the
21+
// HTML always points at the freshly-named asset, so consumers download the
22+
// new bytes on the first navigation after a deploy.
23+
1824
export default {
1925
input: "examples/demo.ts",
2026
output: {
21-
file: "docs/bundle.js",
27+
dir: "docs",
28+
entryFileNames: "bundle-[hash].js",
2229
format: "iife",
2330
inlineDynamicImports: true,
2431
sourcemap: false
@@ -35,9 +42,22 @@ export default {
3542
compress: {passes: 2}
3643
}),
3744
{
38-
name: "copy-html-shell",
39-
writeBundle() {
40-
copyFileSync("examples/index.html", "docs/index.html")
45+
name: "html-with-hashed-bundle",
46+
// Runs after Rollup decides on chunk names; we pick up the actual
47+
// emitted filename and inject it into the HTML shell.
48+
writeBundle(_, bundle) {
49+
const entry = Object.values(bundle).find(c => c.type === "chunk" && c.isEntry)
50+
if (!entry) throw new Error("rollup-plugin html-with-hashed-bundle: no entry chunk")
51+
const html = readFileSync("examples/index.html", "utf8")
52+
.replace(/\.\/bundle(?:-[^"]+)?\.js/, `./${entry.fileName}`)
53+
writeFileSync("docs/index.html", html)
54+
// Clean up stale bundle-*.js files from previous builds so we don't
55+
// pile them up across rebuilds.
56+
for (const f of readdirSync("docs")) {
57+
if (/^bundle-.*\.js$/.test(f) && f !== entry.fileName) {
58+
rmSync(`docs/${f}`)
59+
}
60+
}
4161
}
4262
}
4363
]

0 commit comments

Comments
 (0)