The biggest barrier to browser-based AI is load time. A 22MB transformer model doesn't load instantly, especially on mobile. ReLU.chat uses service workers to eliminate this friction.
The Loading Strategy
On first visit, the service worker installs and pre-caches critical assets:
- App shell: HTML, CSS, JS modules, fonts (~200 KB)
- Model files: MiniLM ONNX quantized (22 MB), policy weights (363 KB), WASM runtimes
- Transformers.js: The ONNX runtime library
On subsequent visits, all assets are served from Cache API — zero network requests.
Cache Architecture
Two separate caches:
relu-chat-v8: App assets (HTML, CSS, JS, fonts)relu-chat-models-v8: Model files (ONNX, weights, WASM)
Model files use cache-first strategy: if cached, serve immediately. Static assets use stale-while-revalidate: serve cached, update in background.
Range Request Support
Large model files (22 MB) benefit from partial loading. The service worker handles Range headers by slicing cached full responses into 206 Partial Content responses. This allows the ONNX runtime to stream-load models efficiently.
Background Preloading
After activation, the service worker preloads model assets in the background:
e.waitUntil(
caches.open(MODEL_CACHE).then(c =>
Promise.allSettled(MODEL_PRELOAD_ASSETS.map(asset => c.add(asset)))
)
);
This means the model is cached before the user even opens a chat page.
Progressive Loading Stages
The chatbot doesn't wait for everything to load:
- Immediate: BOW + heuristic fallback (instant, uses built-in vocabulary)
- Fast: MLP policy loads (~100ms, JSON fetch)
- Medium: Transformer model loads (~5-15s, 22 MB)
- Background: WASM acceleration (optional)
The user can start chatting at stage 1. The system hot-swaps to better engines as they load.
Key Takeaway
Service workers transform a 22 MB model from a blocking download into a one-time cost. After the first visit, chatbot startup is instant.