cache-busting query string in build for worker files

This commit is contained in:
Steven Hugg committed 2026-10-23 14:54:30 +02:00
1 parent 709857a18e
commit c017ca1b9b
6 files changed
+29 -10

No files matched your search

+1
View File
@@ -13,6 +13,7 @@
### Editor and UI
- The IDE now works in Firefox: a synchronous XHR with a `responseType` hangs in Firefox when the response is 1MB or more, so the build worker hung forever on platforms with a big toolchain package (Game Boy, Atari 8-bit, Apple II, ...). The worker now fetches those packages as ArrayBuffers. A worker that dies no longer leaves the IDE spinning: the error is shown and the build stops.
- Firefox no longer serves a stale build worker or toolchain package after an update: its hard reload (cmd+shift+r) doesn't revalidate requests made from a worker. The IDE now puts a build id in the worker URL, and the worker passes it on to every package and library it fetches.
## [4.0.0] - 2026-10-21
+4
View File
@@ -12,6 +12,9 @@
import esbuild from 'esbuild';
import mdPlugin from './md-loader.mjs';
// identifies this build; the IDE puts it in the worker URL to defeat stale caches
const define = { __BUILD_ID__: JSON.stringify(Date.now().toString(36)) };
const configs = {
worker: {
entryPoints: ['src/worker/workermain.ts'],
@@ -54,6 +57,7 @@ for (const name of targets) {
}
const ctx = await esbuild.context({
...config,
define,
plugins: [mdPlugin],
});
if (watch) {
+5 -1
View File
@@ -47,6 +47,7 @@ import { findListingLocation as findListingLocationPure } from "./search/listing
import DOMPurify = require("dompurify");
// external libs (TODO)
declare var __BUILD_ID__: string; // defined by scripts/build.mjs
declare var Tour;
declare var $: JQueryStatic; // use browser jquery
@@ -132,7 +133,10 @@ export function getWorkerParams() {
function newWorker(): Worker {
// TODO: return new Worker("https://8bitworkshop.com.s3-website-us-east-1.amazonaws.com/dev/gen/worker/bundle.js");
return new Worker("./gen/worker/bundle.js");
// The build id in the query string makes Firefox refetch the bundle after a
// rebuild (hard reload doesn't cover workers); the worker reuses it for its
// own fetches via cacheBust().
return new Worker("./gen/worker/bundle.js" + (typeof __BUILD_ID__ != 'undefined' ? '?v=' + __BUILD_ID__ : ''));
}
const hasLocalStorage: boolean = function () {
+11 -1
View File
@@ -10,6 +10,16 @@ import { TOOLS } from "./workertools";
const PSRC = "../../src/";
export const PWORKER = PSRC + "worker/";
/**
* Append the worker's own query string (the IDE's build id, see newWorker()
* in ide/ui.ts) to a URL the worker fetches. Firefox's hard reload does not
* revalidate requests made from a worker, so without this a stale bundle or
* toolchain package survives cmd+shift+r. Empty in node tests.
*/
export function cacheBust(url: string): string {
return url + ((typeof location != 'undefined' && location.search) || '');
}
export type FileData = string | Uint8Array;
export type FileEntry = {
@@ -423,7 +433,7 @@ export function populateExtraFiles(step: BuildStep, fs, extrafiles, processFn?:
export function fetchLibraryFile(platform: string, name: string): Uint8Array | null {
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open("GET", PWORKER + "lib/" + getBasePlatform(platform) + "/" + name, false); // synchronous request
xhr.open("GET", cacheBust(PWORKER + "lib/" + getBasePlatform(platform) + "/" + name), false); // synchronous request
xhr.send(null);
return xhr.response && xhr.status == 200 ? new Uint8Array(xhr.response) : null;
}
+2 -2
View File
@@ -1,7 +1,7 @@
import JSZip from 'jszip';
import { WASIRunner, WASIMemoryFilesystem } from "../common/wasi/wasishim";
import { WorkerError } from "../common/workertypes";
import { BuildStep, store } from "./builder";
import { BuildStep, cacheBust, store } from "./builder";
import { hasErrors, re_crlf } from "./listingutils";
import { ensureWasiFilesystem, loadWASMBinary, makeBlob } from "./wasmutils";
@@ -10,7 +10,7 @@ export function loadBlobSync(path: string) {
// arraybuffer, not blob: Firefox hangs on a synchronous XHR with
// responseType='blob' for responses of 1MB or more (see wasmutils.makeBlob)
xhr.responseType = 'arraybuffer';
xhr.open("GET", path, false); // synchronous request
xhr.open("GET", cacheBust(path), false); // synchronous request
xhr.send(null);
return makeBlob(xhr.response);
}
+6 -6
View File
@@ -2,7 +2,7 @@
// WebAssembly module cache
// for Emscripten-compiled functions
import { BuildStep, PWORKER, endtime, starttime, putWorkFile, anyTargetChanged } from "./builder";
import { BuildStep, PWORKER, cacheBust, endtime, starttime, putWorkFile, anyTargetChanged } from "./builder";
/// <reference types="emscripten" />
export interface EmscriptenModule {
@@ -151,12 +151,12 @@ export function getFilesystemSize(name: string): number {
export function loadFilesystem(name: string) {
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open("GET", PWORKER + "fs/fs" + name + ".data", false); // synchronous request
xhr.open("GET", cacheBust(PWORKER + "fs/fs" + name + ".data"), false); // synchronous request
xhr.send(null);
fsBlob[name] = makeBlob(xhr.response);
xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open("GET", PWORKER + "fs/fs" + name + ".js.metadata", false); // synchronous request
xhr.open("GET", cacheBust(PWORKER + "fs/fs" + name + ".js.metadata"), false); // synchronous request
xhr.send(null);
fsMeta[name] = xhr.response;
console.log("Loaded " + name + " filesystem", fsMeta[name].files.length, 'files', fsBlob[name].size, 'bytes');
@@ -165,7 +165,7 @@ export function loadFilesystem(name: string) {
var loaded = {};
export function load(modulename: string, debug?: boolean) {
if (!loaded[modulename]) {
importScripts(PWORKER + 'asmjs/' + modulename + (debug ? "." + debug + ".js" : ".js"));
importScripts(cacheBust(PWORKER + 'asmjs/' + modulename + (debug ? "." + debug + ".js" : ".js")));
loaded[modulename] = 1;
}
}
@@ -173,7 +173,7 @@ export function loadWASMBinary(modulename: string) {
if (!loaded[modulename]) {
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open("GET", PWORKER + "wasm/" + modulename + ".wasm", false); // synchronous request
xhr.open("GET", cacheBust(PWORKER + "wasm/" + modulename + ".wasm"), false); // synchronous request
xhr.send(null);
if (xhr.response) {
wasmBlob[modulename] = new Uint8Array(xhr.response);
@@ -187,7 +187,7 @@ export function loadWASMBinary(modulename: string) {
}
export function loadWASM(modulename: string, debug?: boolean) {
if (!loaded[modulename]) {
importScripts(PWORKER + "wasm/" + modulename + (debug ? "." + debug + ".js" : ".js"));
importScripts(cacheBust(PWORKER + "wasm/" + modulename + (debug ? "." + debug + ".js" : ".js")));
loadWASMBinary(modulename);
}
}