Diagnostics
LUM4004: Browser API at module scope
A module that runs on the server uses a browser API at module scope.
Severity: warning · Category: islands and boundaries (4xxx)
Reported by: the compiler, for .stsx/.tsx modules: @lumiose/vite when it compiles a
module for the server (lumiose dev and lumiose build print the warning), and lumiose check and the
language server for every module except client entries (modules that import lumiose/dom) and spa
routes with export const ssr = false. A warning.
#What it means
Components are imported on the server for SSR. window, document, localStorage and similar
globals do not exist there, so touching them while the module loads crashes the server render.
#Example
const saved = localStorage.getItem("theme");
export function ThemeToggle() {
return <button>{saved}</button>;
}Reported: window, document, localStorage, sessionStorage, navigator, location,
history, matchMedia, requestAnimationFrame, customElements, IntersectionObserver and
similar browser-only globals, when they are evaluated at module scope. Not reported: code inside a
function (a component, an effect, an event handler, onMount) or a class, a typeof window
check, code guarded by one (typeof window !== "undefined" && …, if (typeof document === "object") { … }), and a local or imported binding with the same name. Plain .ts modules are not
analysed.
#How to fix it
Read browser APIs inside onMount, an effect or an event handler, which only run in the browser:
export function ThemeToggle() {
const theme = signal("light");
onMount(() => theme.set(localStorage.getItem("theme") ?? "light"));
return <button>{theme()}</button>;
}