Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/app/docs/no-build/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default function NoBuild() {
<link rel="modulepreload" href="/components/avatar.ts">
&lt;link rel="modulepreload" href="/lib/format-date.ts"&gt;</pre>
<p>This converts a sequential <code>import</code> waterfall into a parallel fetch. The browser fires every request as soon as the HTML head is parsed, well before <code>&lt;script type="module"&gt;</code> at the bottom would have discovered them.</p>
<p>Server-only modules (filename matches <code>.server.{js,ts}</code> or content has a <code>'use server'</code> directive) are excluded from preload hints. They never reach the browser as source. Lazy components (<code>static lazy = true</code>) are also excluded, since they load on viewport entry via IntersectionObserver, not page load.</p>
<p>Server-only modules (filename matches <code>.server.{js,ts}</code> or content has a <code>'use server'</code> directive) are excluded from preload hints, and the dependency walk <strong>stops at</strong> them: a plain module reached only through a server file (a util that a server action imports) is excluded too. The browser only ever fetches the action's RPC stub, never the server file's own imports, so the preload set is exactly the set the page actually fetches. None of it reaches the browser as source. Lazy components (<code>static lazy = true</code>) are also excluded, since they load on viewport entry via IntersectionObserver, not page load.</p>
<p><strong>Display-only components are excluded too, and not just from preloads.</strong> A component whose <code>render()</code> is a pure function of its inputs (no <code>@event</code> handler, no non-<code>state</code> reactive property, no overridden lifecycle hook, no signal / <code>Task</code> / streaming directive, no <code>&lt;slot&gt;</code>) does no client-side work, so its SSR'd HTML is the complete output. The server detects this statically and strips its side-effect import from the served page source, so the browser never downloads the module at all, and any npm package imported only by display-only components drops out of the importmap. This is the no-build equivalent of React Server Components' dead-JS elimination, with no bundler and no server/client directive. The analysis is conservative: anything it cannot prove inert keeps shipping. See <a href="/docs/progressive-enhancement">Progressive Enhancement</a>.</p>

<h3>The module graph is also the authorisation gate</h3>
Expand Down