Prerender build fails when component accesses window during static generation
0 reputation · 17 Mar 2025, 20:57 UTC
0 reputation · 17 Mar 2025, 20:57 UTC
StencilJS prerendering executes component code in a Node.js environment, so reading window or document outside a browser-safe lifecycle can fail the static-build step. The goal is to confirm whether StencilJS provides a build-time override that automatically polyfills browser globals during prerendering, or whether each component author must add manual runtime guards.
The @Component encapsulation mode (shadow or scoped DOM) does not change this Node.js execution context, and available documentation does not describe an automatic prerender polyfill flag. Configuration keys and behavior may differ across StencilJS major versions.
Does StencilJS provide a production-build or prerender option to shim browser globals automatically? If not, is manual guarding the only supported approach, and which lifecycle hooks reliably run only in the browser during static generation?
34775 reputation · 18 Mar 2025, 01:20 UTC
StencilJS does not provide a built-in production-build option or configuration flag to automatically shim or polyfill browser globals (such as window or document) during the prerendering process. Manual guarding is the only supported approach to prevent build-time failures when components are executed in the Node.js environment during static generation.
During prerendering, StencilJS executes your component logic within Node.js to generate static HTML. Because Node.js lacks a DOM, any direct reference to window, document, or localStorage outside of a browser-safe context will throw a ReferenceError and crash the build process.
It is important to note that @Component encapsulation modes (Shadow DOM or Scoped DOM) only affect how the browser renders the final output; they do not isolate the Node.js execution environment from these missing globals during the build phase.
To ensure browser-specific logic only runs on the client, use the following strategies:
componentDidLoad(): This is the most reliable hook for browser-only logic. It does not execute during the static prerendering phase, making it the ideal location for initializing third-party libraries or accessing the window object.render() method or the constructor, use a type check:
if (typeof window !== 'undefined') {
// Browser-safe logic here
}
You can verify the environment behavior using these scoped tests:
console.log(window.location.href) directly inside the render() method. Run your build command with prerendering enabled; the build should fail.console.log into componentDidLoad(). The build should now complete successfully, and the log will only appear in the browser's developer console at runtime.Diagnostic Note: To provide more specific guidance, please confirm which version of StencilJS you are using, as lifecycle behavior is subject to change across major versions.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 18 Mar 2025, 06:46 UTC
Stencil doesn’t inject a window shim during prerendering. The recommended pattern is to import the isBrowser helper from @stencil/core and wrap any DOM‑dependent code in that guard, or move it to componentDidLoad() where it runs only in the browser.
import { isBrowser } from '@stencil/core';
if (isBrowser) {
// safe to use window, document, localStorage
}
This pattern keeps the build process clean and ensures the same code path works both in Node and the browser.