Commit bb4586a
fix: avoid full-reload in scss modules (#14924)
* fix: avoid full-reload in scss modules
* fix: improve regex
* fix: ci
* test: add test for modules
* fix(hmr): prevent full-reload for SCSS/CSS module changes
SCSS and CSS module file changes were triggering unnecessary full page
reloads during development instead of applying HMR updates. This broke
the developer experience by losing component state and scroll position
on every style edit.
Root cause: In the `astro:hmr-reload` Vite plugin, style files (CSS,
SCSS, SASS, LESS, etc.) in the SSR module graph were correctly skipped
via a regex check, but the handler returned `undefined` instead of an
empty array. In Vite 6, returning `undefined` from a `hotUpdate` hook
means "I didn't handle this", causing Vite to propagate through the SSR
module graph to `.astro` importers. Since `.astro` pages have no HMR
boundary, this triggered a full page reload.
Changes to `vite-plugin-hmr-reload`:
- Extract `isStyleModule()` helper that checks both `mod.file` and
`mod.id` (stripping query params like `?inline`, `?used`) against
the style extension regex. This correctly identifies all style-related
modules including CSS module variants.
- Return `[]` (empty array) when only style modules were encountered
in the SSR environment. This tells Vite "handled, nothing to update
in SSR", preventing the propagation chain that caused full reloads.
The client environment handles CSS HMR natively through
framework-specific HMR boundaries (Preact, React, Vue, etc.).
Changes to e2e test fixtures:
- Update the SCSS module HMR test to use a Preact component with
`client:load` instead of a pure server-rendered Astro page. This
matches the real-world scenario from the original bug report (issue
#14869) where Preact + SCSS modules triggered full reloads. CSS
module HMR requires a client-side framework to re-render components
with updated class name hashes — pure SSR pages cannot hot-update
CSS module class names without a full reload.
Closes #14869
* fix(hmr): clarify comment about CSS HMR working for all pages
The previous comment suggested CSS HMR only worked through
framework-specific boundaries. Vite's built-in style update
mechanism handles it for all pages, with or without framework
components (covered by the scss-external test).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* update pnpm-lock.yaml
* chore: add changeset for SCSS/CSS module HMR fix
---------
Co-authored-by: Erika <3019731+Princesseuh@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Matthew Phillips <matthew@matthewphillips.info>
Co-authored-by: Matthew Phillips <matthewphillips@cloudflare.com>1 parent 5f3085b commit bb4586a
11 files changed
Lines changed: 114 additions & 0 deletions
File tree
- .changeset
- packages/astro
- e2e
- fixtures/hmr
- src
- components
- pages
- styles
- src/vite-plugin-hmr-reload
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
5 | 9 | | |
6 | 10 | | |
7 | 11 | | |
| |||
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
Lines changed: 11 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
Lines changed: 12 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
Lines changed: 3 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
Lines changed: 3 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
87 | 117 | | |
88 | 118 | | |
89 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
6 | 18 | | |
7 | 19 | | |
8 | 20 | | |
| |||
18 | 30 | | |
19 | 31 | | |
20 | 32 | | |
| 33 | + | |
21 | 34 | | |
22 | 35 | | |
23 | 36 | | |
24 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
25 | 43 | | |
26 | 44 | | |
27 | 45 | | |
| |||
45 | 63 | | |
46 | 64 | | |
47 | 65 | | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
48 | 76 | | |
49 | 77 | | |
50 | 78 | | |
| |||
0 commit comments