Skip to content

2.0.0-rc.3 | Updates in Document.jsx won't HRM update #3151

Closed

Description

@karimmaassen

Describe the bug

Might seem as a silly issue, but any updates on Document.jsx won't hot reload the module. I've added some Tailwind classes on and they only show up in my running app when I manually refresh. The same goes for adding/removing DOM elements, such as an

inside the .

Your Example Website or App

solid 2.0 rc-3

Steps to Reproduce the Bug or Issue

Install solid 2.0 rc-3 (or 4) and try and edit Document.jsx:

<html 
      lang="en" 
      class="bg-slate-900 overscroll-x-none overflow-x-hidden sm:overscroll-contain scroll-smooth">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" type="image/svg+xml" href="/favicon.svg?v=2" />
        <link rel="icon" href="/favicon.ico?v=2" />
        <title>Solid App</title>
        <HydrationScript />
      </head>
      <body class="h-dvh isolate">
        <h1>Hello Solid</h1>
        {props.children}
      </body>
</html>

Expected behavior

I expect the HMR to kick in on saving Document.jsx.

Screenshots or Videos

No response

Platform

  • OS: MacOS 26.5
  • Browser: Safari
  • Version: 26.5

Additional context

No response

Activity

  1. ryansolid commented on Aug 31, 2026

    @ryansolid
    Member

    Thanks for the report. This is very likely @solidjs/vite-plugin territory rather than core: the document shell (<html>/<head>, HydrationScript) is server-rendered and can't hot-swap like a component, so the expected behavior on a Document edit is a triggered full reload — and it sounds like not even that is happening. To pin it down, could you share which template you started from, your @solidjs/vite-plugin version, and whether editing a regular route component does HMR correctly in the same app? We're tracking it for the plugin either way.

  2. ryansolid commented on Aug 31, 2026

    @ryansolid
    Member

    Triage: not silly at all, and reproducible by inspection. A module rendering the document shell (<html>/<head>/<body>) can never hot-swap — the markup it produces is the server-rendered scaffolding the client already claimed at hydration, and there is no boundary to re-render under (replacing document.documentElement live would tear down the whole app anyway). Today solid-refresh wraps or accepts the module like any other component, so the update is absorbed silently and nothing visibly changes — the worst of both worlds.

    The correct behavior is for the transform to recognize document-shell modules and decline HMR for them (import.meta.hot.decline()), which makes Vite fall back to a full page reload on save — your Tailwind classes on <html> would then show up immediately, at the cost of a reload, which is the honest cost. The fix belongs in @solidjs/vite-plugin / solid-refresh rather than the core runtime, so it ships on the plugin's release cadence rather than with core rc.5. Leaving this open until it lands there.

  3. ryansolid commented on Aug 31, 2026

    @ryansolid
    Member

    Fixed in solidjs/solid-vite-plugin#336. The mechanism turned out to be two-sided, both in the vite plugin's dev serving:

    • In SSR start mode the client entry hydrates the whole document, so your Document.jsx is a real client module — the HMR transform wrapped it like any component and the update was accepted and silently absorbed (no swap can re-claim document.documentElement). The plugin now declines HMR for the resolved document module specifically, so saving it triggers a full page reload — your Tailwind classes on <html> show up immediately at the honest cost of a reload.
    • In client (SPA) mode the document is server-graph-only, and server-side updates were suppressed entirely; those now also full-reload the browser.

    Ships with the next @solidjs/vite-plugin release; no core change needed.

  4. karimmaassen commented on Sep 1, 2026

    @karimmaassen
    Author

    That's a swift update indeed!

    The plugin now declines HMR for the resolved document module specifically, so saving it triggers a full page reload — your Tailwind classes on show up immediately at the honest cost of a reload.

    Makes sense.

  5. ryansolid commented on Sep 1, 2026

    @ryansolid
    Member

    Fixed in 4da3fb4 on next — the compiler's refresh pass now detects document-shell modules (intrinsic html/head/body) and takes the @refresh reload path (a decline block), so editing Document.jsx triggers a full reload that fetches a fresh server render. A document shell can't hot-swap: its elements compile with no client template (only recoverable from the hydration walk) and its static markup exists only in the server HTML. Ships in the next RC.

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

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