Skip to content

fix(preloader): prioritize render dependencies over event code - #9384

Open
Varixo wants to merge 2 commits into
codex/smaller-preloaderfrom
codex/render-preload-priorities
Open

Varixo wants to merge 2 commits into
codex/smaller-preloaderfrom
codex/render-preload-priorities

Conversation

@Varixo

@Varixo Varixo commented Nov 5, 2026

Copy link
Copy Markdown
Member

The smart preload graph treats render-time QRL calls and future interactions alike, so navigation can compete with event-only code or discover render dependencies too late. Emit the existing event-only classification from both optimizers, derive conservative render edges from module metadata, and prioritize their bounded static/render closure in the preload queue. Unknown consumers, custom hooks, helpers and compiled libraries stay reachable.

Update the graph writer and reader together, retaining the existing SSR/client context classification. Renderer execution order stays unchanged.

Depends only on #9382. On main alone the production fixture's preloader is 1967 B Brotli, exceeding the existing 1800 B ceiling; with #9382 it is 1613 B. Merge #9382 first, then retarget this PR to main. The navigation PR #9383 targets main independently and is not required here.

Validation:

  • 384 Rust optimizer tests.
  • 401 TS optimizer, snapshot parser and full Rust-snapshot convergence tests.
  • 144 focused queue, standalone-preloader, manifest, graph round-trip and compiled-library integration tests across both optimizers.
  • Regenerated public API via pnpm api.update; production build passes.
  • Production SSG snapshots and unchanged bundle budgets pass on TS and Rust (6 tests each).
  • Prettier and git diff --check pass.

The combined PR trees reproduce the original benchmark implementation; only changeset grouping and test placement differ. No new Firefox 3G/Good 2G performance comparison was run for this extraction.

@changeset-bot

changeset-bot Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c2fa12b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@qwik.dev/core Patch
@qwik.dev/optimizer Patch
@qwik.dev/devtools Patch
eslint-plugin-qwik Patch
@qwik.dev/mcp Patch
@qwik.dev/react Patch
@qwik.dev/router Patch
@qwik.dev/utils Patch
create-qwik Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3094dad0-5878-480c-99f7-9ae1780d76ce

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@maiieul maiieul moved this to In progress in Qwik Development Nov 5, 2026
@pkg-pr-new

pkg-pr-new Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@qwik.dev/core

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/core@9384

@qwik.dev/router

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/router@9384

@qwik.dev/utils

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/utils@9384

eslint-plugin-qwik

npm i https://pkg.pr.new/QwikDev/qwik/eslint-plugin-qwik@9384

create-qwik

npm i https://pkg.pr.new/QwikDev/qwik/create-qwik@9384

@qwik.dev/optimizer

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/optimizer@9384

@qwik.dev/devtools

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/devtools@9384

@qwik.dev/mcp

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/mcp@9384

commit: c2fa12b

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

⚡ Docs preview for c2fa12b

@maiieul

maiieul commented Nov 6, 2026

Copy link
Copy Markdown
Member

The smart preload graph treats render-time QRL calls and future interactions alike, so navigation can compete with event-only code or discover render dependencies too late
General approach LGTM.

In which case does it discover render deps too late?

Should we preload uncertain deps together with the render ones or after?

@Varixo

Varixo commented Nov 6, 2026

Copy link
Copy Markdown
Member Author

The smart preload graph treats render-time QRL calls and future interactions alike, so navigation can compete with event-only code or discover render dependencies too late
General approach LGTM.

In which case does it discover render deps too late?

Should we preload uncertain deps together with the render ones or after?

  1. A QRL facade missing from the preload path
// product.js
const renderProduct = qrl(
  () => import("./render-entry.js"),
  "renderProduct"
);

// render-entry.js — facade
export { renderImpl as renderProduct } from "./render-impl.js";

// render-impl.js
export function renderImpl() {
  return /* product UI */;
}

The actual import path is:
product.js -> render-entry.js -> render-impl.js

But the old preload graph points directly to the implementation:
product.js -> render-impl.js

  1. An uncertain QRL that is actually needed during rendering
// hooks.js
export function usePriceReader() {
  return $(() => calculatePrice());
}

export function invoke(callback) {
  return callback();
}

// Product component — pseudocode
async function renderProduct() {
  const readPrice = usePriceReader();
  const price = await invoke(readPrice);

  return <span>{price}</span>;
}

If we deferred uncertain dependencies until known render dependencies finished, we could get:
download component

  • execute render
  • invoke helper
  • start downloading calculatePrice QRL
  • finish render
    That introduces a waterfall.

Compiled client wrappers can retain server context labels. Excluding them drops serializer preloads before the first server call.
@maiieul
maiieul force-pushed the codex/smaller-preloader branch from 7307527 to a73ecbc Compare November 8, 2026 11:24
@maiieul
maiieul force-pushed the codex/render-preload-priorities branch from 255df7c to c2fa12b Compare November 8, 2026 11:24
@Varixo
Varixo marked this pull request as ready for review November 8, 2026 16:23
@Varixo
Varixo requested review from a team as code owners November 8, 2026 16:23
@maiieul maiieul moved this from In progress to Waiting For Review in Qwik Development Nov 8, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Waiting For Review

Development

Successfully merging this pull request may close these issues.

2 participants