Skip to content

qwikloader: WebKit may defer the async module loader while a stream is held, losing pre-resume clicks #8891

Description

@maiieul

What is it?

  • Bug

Description

With the default loader emission (QwikLoaderInclude.Module: <link rel="modulepreload"> + <script async type="module" src=".../qwikloader.js">), WebKit sometimes never evaluates the loader while the HTML stream is held open (e.g. an in-order region awaiting a deferred child). Until evaluation, no qwikloader listeners exist, so user clicks during the hold are lost instead of queued and replayed at resume. Chromium evaluates the async module as soon as it is fetched and queues the clicks correctly.

Observed on the error-handling e2e app's midstream route (in-order streaming, stream held by a gated Suspense child): window._qwikEv.roots (set only by loader evaluation) never appears on WebKit within 90s, both on CI (macos-latest) and locally (macOS 26.5 / Playwright WebKit 26.5), while the same page's inline scripts (qErr swap) run fine. The behavior is bimodal — some runs evaluate promptly — so it looks like WebKit only drains ready async scripts on parser activity, and a fully quiet hold starves them. Streaming extra padding bytes mid-hold did not reliably help.

Production impact: any Qwik page whose stream stalls (slow loader, held Suspense region) has a WebKit window where clicks are dropped instead of queued.

Possible direction: emit the Module include as a tiny inline classic script that dynamic-imports the loader (<script>import("…/qwikloader.js")</script>, nonce-aware). Dynamic import evaluation rides the microtask queue, not the parser's async-script runner, so it is immune to the starvation. Needs verification on WebKit.

The error-handling.e2e.ts mid-stream queue-and-replay test parks WebKit on this issue (the invariant stays pinned on Chromium, Linux + Windows).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions