Repository navigation
fix(client): skip rewriting unchanged adopted styles - #23697
Merged
Merged
Conversation
`updateStyle` reuses a server-rendered `<style data-vite-dev-id>` and then sets its `textContent` to the module's CSS, even when the text is already the same. Chrome 154 replaces the stylesheet on that write and re-creates the font faces it declares. Those fonts are then revalidated, since the dev server serves them with `Cache-Control: no-cache`, and a `font-display: optional` font that is still loading when the page renders stays on its fallback. Only write the CSS when it differs.
Member
|
It seems this is related to https://chromium-review.googlesource.com/c/chromium/src/+/8252693. But regardless of that, I think it's good to have this change. |
sapphi-red
approved these changes
Oct 8, 2026
This was referenced Oct 8, 2026
Merged
renovate Bot
added a commit
to andrei-picus-tink/auto-renovate
that referenced
this pull request
Oct 9, 2026
| datasource | package | from | to | | ---------- | ------- | ----- | ----- | | npm | vite | 8.3.0 | 8.3.4 | ## [v8.3.4](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-834-2026-10-08-small) ##### Features - **bundled-dev:** support `import.meta.hot.acceptExports` ([#23463](vitejs/vite#23463)) ([bc0f21c](vitejs/vite@bc0f21c)) ##### Bug Fixes - avoid mutating hmr defaults (fix [#23575](vitejs/vite#23575)) ([#23576](vitejs/vite#23576)) ([574d5e3](vitejs/vite@574d5e3)) - **build:** correct preloads when chunkImportMap is enabled with non-root base ([#23698](vitejs/vite#23698)) ([2a8c0f0](vitejs/vite@2a8c0f0)) - **build:** wait for in-flight stylesheets in preload helper (fix [#23652](vitejs/vite#23652)) ([#23662](vitejs/vite#23662)) ([036b745](vitejs/vite@036b745)) - **bundled-dev:** serve `/@vite/client` and stub `@vite/env` ([#23664](vitejs/vite#23664)) ([5afc5a8](vitejs/vite@5afc5a8)) - **client:** skip rewriting unchanged adopted styles ([#23697](vitejs/vite#23697)) ([fa71469](vitejs/vite@fa71469)) - **css:** resolve imported preprocessors from their file path with lightningcss ([#23688](vitejs/vite#23688)) ([cf52011](vitejs/vite@cf52011)) - **deps:** update all non-major dependencies ([#23648](vitejs/vite#23648)) ([8a4c19c](vitejs/vite@8a4c19c)) - **deps:** update rolldown-related dependencies ([#23649](vitejs/vite#23649)) ([794516d](vitejs/vite@794516d)) - **dev:** a restart requested during a restart used to be dropped (fix [#23392](vitejs/vite#23392)) ([#23484](vitejs/vite#23484)) ([70d56ea](vitejs/vite@70d56ea)) - don't treat modules ending with js-like query as js ([#23687](vitejs/vite#23687)) ([fcb6f12](vitejs/vite@fcb6f12)) - **html:** avoid adding filesystem root to watcher ([#23689](vitejs/vite#23689)) ([3a7f2ae](vitejs/vite@3a7f2ae)) - **html:** skip caching CSS of chunks in a cycle (fix [#23628](vitejs/vite#23628)) ([#23636](vitejs/vite#23636)) ([15d82f7](vitejs/vite@15d82f7)) - **optimizer:** scan deep imports with custom extensions ([#23678](vitejs/vite#23678)) ([8579189](vitejs/vite@8579189)) - remove input option unescaping for now ([#23694](vitejs/vite#23694)) ([facc2fb](vitejs/vite@facc2fb)) - **server:** match static aliases on path boundaries ([#23643](vitejs/vite#23643)) ([b28db28](vitejs/vite@b28db28)) - **watcher:** normalize file before root check in `ensureWatchedFile` ([#23673](vitejs/vite#23673)) ([12bb28c](vitejs/vite@12bb28c)) ##### Performance Improvements - **module-runner:** skip cloning call sites that have no source map ([#23646](vitejs/vite#23646)) ([3d67486](vitejs/vite@3d67486)) ##### Code Refactoring - **bundled-dev:** import CSS HMR helpers from `/@vite/client` ([#23674](vitejs/vite#23674)) ([182f5b2](vitejs/vite@182f5b2)) ## [v8.3.3](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-833-2026-10-06-small) ##### Bug Fixes - **deps:** update launch-editor to v2.14.2 ([#23654](vitejs/vite#23654)) ([22fd1d5](vitejs/vite@22fd1d5)) - **html:** filename passed to transformIndexHtml should not include queries ([#23653](vitejs/vite#23653)) ([7dafd8e](vitejs/vite@7dafd8e)) - **server:** check `fs.serve` for `?vite-wasm-instance` ([#23655](vitejs/vite#23655)) ([ba8b7ab](vitejs/vite@ba8b7ab)) - **server:** store ids to `safeModulePaths` rather than URLs ([#23656](vitejs/vite#23656)) ([c3e06f9](vitejs/vite@c3e06f9)) ## [v8.3.2](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-832-2026-10-01-small) ##### Bug Fixes - **build:** preload CSS correctly when `renderBuiltUrl` returns URLs with queries ([#23611](vitejs/vite#23611)) ([64e0a21](vitejs/vite@64e0a21)) - **bundled-dev:** serve lazy chunk sourcemaps ([#23026](vitejs/vite#23026)) ([eb7aa9a](vitejs/vite@eb7aa9a)) - **bundled-dev:** serve the rolldown runtime from the installed rolldown ([#23568](vitejs/vite#23568)) ([bc598a6](vitejs/vite@bc598a6)) - **deps:** update all non-major dependencies ([#23601](vitejs/vite#23601)) ([9944fa6](vitejs/vite@9944fa6)) - **deps:** update rolldown-related dependencies ([#23602](vitejs/vite#23602)) ([88c1741](vitejs/vite@88c1741)) - **html:** resolve percent-encoded srcset urls ([#23609](vitejs/vite#23609)) ([53f1ce7](vitejs/vite@53f1ce7)) - limit size of object and array printing via `forwardConsole` ([#23565](vitejs/vite#23565)) ([e64a587](vitejs/vite@e64a587)) - merge `build.rolldownOptions.output.minify` correctly ([#23536](vitejs/vite#23536)) ([bba3bb8](vitejs/vite@bba3bb8)) - **optimize-deps:** avoid "unsupported" warnings for browser:false mappings ([#23590](vitejs/vite#23590)) ([5e4b9ca](vitejs/vite@5e4b9ca)) - **optimizer:** preserve excluded optional peer require fallbacks ([#23600](vitejs/vite#23600)) ([a2bd6fa](vitejs/vite@a2bd6fa)) - pass queries to `renderBuiltUrl` ([#23586](vitejs/vite#23586)) ([744269e](vitejs/vite@744269e)) - **server:** handle file watcher errors without crashing ([#23503](vitejs/vite#23503)) ([6894f5c](vitejs/vite@6894f5c)) - **server:** release previous environments after initialization ([#23499](vitejs/vite#23499)) ([5a3a010](vitejs/vite@5a3a010)) - **ssr:** encode whitespace in module runner sourceURL ([#23513](vitejs/vite#23513)) ([bbc8812](vitejs/vite@bbc8812)) - **worker:** align worker urls in client and server when using terser ([#23614](vitejs/vite#23614)) ([24bd331](vitejs/vite@24bd331)) ##### Performance Improvements - avoid encoding intermediate source maps ([#23461](vitejs/vite#23461)) ([89574f6](vitejs/vite@89574f6)) - **build:** avoid quadratic link scan in the preload helper ([#23510](vitejs/vite#23510)) ([cf5c028](vitejs/vite@cf5c028)) - only register time middleware when debug logging is enabled ([#23621](vitejs/vite#23621)) ([94d0080](vitejs/vite@94d0080)) ##### Documentation - fix dead og-image PNG links in vite6/vite7 changelog entries ([#23594](vitejs/vite#23594)) ([1929b4c](vitejs/vite@1929b4c)) ##### Miscellaneous Chores - **deps:** update vitest monorepo to v5 ([#23604](vitejs/vite#23604)) ([24339f4](vitejs/vite@24339f4)) ##### Code Refactoring - use `tinyexec` instead of `cross-spawn` ([#23583](vitejs/vite#23583)) ([db915e5](vitejs/vite@db915e5)) ##### Tests - **bundled-dev:** accept a rolldown dev runtime with no helper imports ([#23606](vitejs/vite#23606)) ([634745d](vitejs/vite@634745d)) ## [v8.3.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-831-2026-09-24-small) ##### Bug Fixes - **deps:** update all non-major dependencies ([#23482](vitejs/vite#23482)) ([3c752c8](vitejs/vite@3c752c8)) - **deps:** update all non-major dependencies ([#23537](vitejs/vite#23537)) ([e8990c4](vitejs/vite@e8990c4)) - **deps:** update rolldown-related dependencies ([#23483](vitejs/vite#23483)) ([9aecbbf](vitejs/vite@9aecbbf)) - handle `server.ws: false` in mergeConfig ([#23511](vitejs/vite#23511)) ([f68c0d5](vitejs/vite@f68c0d5)) - merge `build.rolldownOptions.output.comments` correctly ([#23514](vitejs/vite#23514)) ([4aba8d8](vitejs/vite@4aba8d8)) - **optimizer:** don't skip imports whose binding starts with type ([#23540](vitejs/vite#23540)) ([39330f4](vitejs/vite@39330f4)) - **optimizer:** resolve pending discovered dep processing on close before init ([#23567](vitejs/vite#23567)) ([5f89433](vitejs/vite@5f89433)) - **server:** avoid reinitializing watcher when adding file after server close ([#23572](vitejs/vite#23572)) ([6f831f9](vitejs/vite@6f831f9)) - **sourcemap:** skip URL source roots when injecting sources content ([#23519](vitejs/vite#23519)) ([04fc30a](vitejs/vite@04fc30a)) ##### Miscellaneous Chores - merge prereleases in changelog ([#23466](vitejs/vite#23466)) ([99bd9d1](vitejs/vite@99bd9d1)) - **optimizer:** add debug log when waiting for dep before init ([#23566](vitejs/vite#23566)) ([63567c7](vitejs/vite@63567c7)) - update `optimizeDeps.include` comment ([#23489](vitejs/vite#23489)) ([6a84c72](vitejs/vite@6a84c72)) ##### Code Refactoring - assets regexp use non-capture ([#23491](vitejs/vite#23491)) ([f4b4431](vitejs/vite@f4b4431)) - remove duplicate configurations ([#23532](vitejs/vite#23532)) ([9abd99b](vitejs/vite@9abd99b)) - replace `find` with `some` ([#23554](vitejs/vite#23554)) ([af7cdf6](vitejs/vite@af7cdf6))
renovate Bot
added a commit
to andrei-picus-tink/auto-renovate
that referenced
this pull request
Oct 10, 2026
| datasource | package | from | to | | ---------- | ------- | ----- | ----- | | npm | vite | 8.3.0 | 8.3.4 | ## [v8.3.4](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-834-2026-10-08-small) ##### Features - **bundled-dev:** support `import.meta.hot.acceptExports` ([#23463](vitejs/vite#23463)) ([bc0f21c](vitejs/vite@bc0f21c)) ##### Bug Fixes - avoid mutating hmr defaults (fix [#23575](vitejs/vite#23575)) ([#23576](vitejs/vite#23576)) ([574d5e3](vitejs/vite@574d5e3)) - **build:** correct preloads when chunkImportMap is enabled with non-root base ([#23698](vitejs/vite#23698)) ([2a8c0f0](vitejs/vite@2a8c0f0)) - **build:** wait for in-flight stylesheets in preload helper (fix [#23652](vitejs/vite#23652)) ([#23662](vitejs/vite#23662)) ([036b745](vitejs/vite@036b745)) - **bundled-dev:** serve `/@vite/client` and stub `@vite/env` ([#23664](vitejs/vite#23664)) ([5afc5a8](vitejs/vite@5afc5a8)) - **client:** skip rewriting unchanged adopted styles ([#23697](vitejs/vite#23697)) ([fa71469](vitejs/vite@fa71469)) - **css:** resolve imported preprocessors from their file path with lightningcss ([#23688](vitejs/vite#23688)) ([cf52011](vitejs/vite@cf52011)) - **deps:** update all non-major dependencies ([#23648](vitejs/vite#23648)) ([8a4c19c](vitejs/vite@8a4c19c)) - **deps:** update rolldown-related dependencies ([#23649](vitejs/vite#23649)) ([794516d](vitejs/vite@794516d)) - **dev:** a restart requested during a restart used to be dropped (fix [#23392](vitejs/vite#23392)) ([#23484](vitejs/vite#23484)) ([70d56ea](vitejs/vite@70d56ea)) - don't treat modules ending with js-like query as js ([#23687](vitejs/vite#23687)) ([fcb6f12](vitejs/vite@fcb6f12)) - **html:** avoid adding filesystem root to watcher ([#23689](vitejs/vite#23689)) ([3a7f2ae](vitejs/vite@3a7f2ae)) - **html:** skip caching CSS of chunks in a cycle (fix [#23628](vitejs/vite#23628)) ([#23636](vitejs/vite#23636)) ([15d82f7](vitejs/vite@15d82f7)) - **optimizer:** scan deep imports with custom extensions ([#23678](vitejs/vite#23678)) ([8579189](vitejs/vite@8579189)) - remove input option unescaping for now ([#23694](vitejs/vite#23694)) ([facc2fb](vitejs/vite@facc2fb)) - **server:** match static aliases on path boundaries ([#23643](vitejs/vite#23643)) ([b28db28](vitejs/vite@b28db28)) - **watcher:** normalize file before root check in `ensureWatchedFile` ([#23673](vitejs/vite#23673)) ([12bb28c](vitejs/vite@12bb28c)) ##### Performance Improvements - **module-runner:** skip cloning call sites that have no source map ([#23646](vitejs/vite#23646)) ([3d67486](vitejs/vite@3d67486)) ##### Code Refactoring - **bundled-dev:** import CSS HMR helpers from `/@vite/client` ([#23674](vitejs/vite#23674)) ([182f5b2](vitejs/vite@182f5b2)) ## [v8.3.3](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-833-2026-10-06-small) ##### Bug Fixes - **deps:** update launch-editor to v2.14.2 ([#23654](vitejs/vite#23654)) ([22fd1d5](vitejs/vite@22fd1d5)) - **html:** filename passed to transformIndexHtml should not include queries ([#23653](vitejs/vite#23653)) ([7dafd8e](vitejs/vite@7dafd8e)) - **server:** check `fs.serve` for `?vite-wasm-instance` ([#23655](vitejs/vite#23655)) ([ba8b7ab](vitejs/vite@ba8b7ab)) - **server:** store ids to `safeModulePaths` rather than URLs ([#23656](vitejs/vite#23656)) ([c3e06f9](vitejs/vite@c3e06f9)) ## [v8.3.2](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-832-2026-10-01-small) ##### Bug Fixes - **build:** preload CSS correctly when `renderBuiltUrl` returns URLs with queries ([#23611](vitejs/vite#23611)) ([64e0a21](vitejs/vite@64e0a21)) - **bundled-dev:** serve lazy chunk sourcemaps ([#23026](vitejs/vite#23026)) ([eb7aa9a](vitejs/vite@eb7aa9a)) - **bundled-dev:** serve the rolldown runtime from the installed rolldown ([#23568](vitejs/vite#23568)) ([bc598a6](vitejs/vite@bc598a6)) - **deps:** update all non-major dependencies ([#23601](vitejs/vite#23601)) ([9944fa6](vitejs/vite@9944fa6)) - **deps:** update rolldown-related dependencies ([#23602](vitejs/vite#23602)) ([88c1741](vitejs/vite@88c1741)) - **html:** resolve percent-encoded srcset urls ([#23609](vitejs/vite#23609)) ([53f1ce7](vitejs/vite@53f1ce7)) - limit size of object and array printing via `forwardConsole` ([#23565](vitejs/vite#23565)) ([e64a587](vitejs/vite@e64a587)) - merge `build.rolldownOptions.output.minify` correctly ([#23536](vitejs/vite#23536)) ([bba3bb8](vitejs/vite@bba3bb8)) - **optimize-deps:** avoid "unsupported" warnings for browser:false mappings ([#23590](vitejs/vite#23590)) ([5e4b9ca](vitejs/vite@5e4b9ca)) - **optimizer:** preserve excluded optional peer require fallbacks ([#23600](vitejs/vite#23600)) ([a2bd6fa](vitejs/vite@a2bd6fa)) - pass queries to `renderBuiltUrl` ([#23586](vitejs/vite#23586)) ([744269e](vitejs/vite@744269e)) - **server:** handle file watcher errors without crashing ([#23503](vitejs/vite#23503)) ([6894f5c](vitejs/vite@6894f5c)) - **server:** release previous environments after initialization ([#23499](vitejs/vite#23499)) ([5a3a010](vitejs/vite@5a3a010)) - **ssr:** encode whitespace in module runner sourceURL ([#23513](vitejs/vite#23513)) ([bbc8812](vitejs/vite@bbc8812)) - **worker:** align worker urls in client and server when using terser ([#23614](vitejs/vite#23614)) ([24bd331](vitejs/vite@24bd331)) ##### Performance Improvements - avoid encoding intermediate source maps ([#23461](vitejs/vite#23461)) ([89574f6](vitejs/vite@89574f6)) - **build:** avoid quadratic link scan in the preload helper ([#23510](vitejs/vite#23510)) ([cf5c028](vitejs/vite@cf5c028)) - only register time middleware when debug logging is enabled ([#23621](vitejs/vite#23621)) ([94d0080](vitejs/vite@94d0080)) ##### Documentation - fix dead og-image PNG links in vite6/vite7 changelog entries ([#23594](vitejs/vite#23594)) ([1929b4c](vitejs/vite@1929b4c)) ##### Miscellaneous Chores - **deps:** update vitest monorepo to v5 ([#23604](vitejs/vite#23604)) ([24339f4](vitejs/vite@24339f4)) ##### Code Refactoring - use `tinyexec` instead of `cross-spawn` ([#23583](vitejs/vite#23583)) ([db915e5](vitejs/vite@db915e5)) ##### Tests - **bundled-dev:** accept a rolldown dev runtime with no helper imports ([#23606](vitejs/vite#23606)) ([634745d](vitejs/vite@634745d)) ## [v8.3.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small-831-2026-09-24-small) ##### Bug Fixes - **deps:** update all non-major dependencies ([#23482](vitejs/vite#23482)) ([3c752c8](vitejs/vite@3c752c8)) - **deps:** update all non-major dependencies ([#23537](vitejs/vite#23537)) ([e8990c4](vitejs/vite@e8990c4)) - **deps:** update rolldown-related dependencies ([#23483](vitejs/vite#23483)) ([9aecbbf](vitejs/vite@9aecbbf)) - handle `server.ws: false` in mergeConfig ([#23511](vitejs/vite#23511)) ([f68c0d5](vitejs/vite@f68c0d5)) - merge `build.rolldownOptions.output.comments` correctly ([#23514](vitejs/vite#23514)) ([4aba8d8](vitejs/vite@4aba8d8)) - **optimizer:** don't skip imports whose binding starts with type ([#23540](vitejs/vite#23540)) ([39330f4](vitejs/vite@39330f4)) - **optimizer:** resolve pending discovered dep processing on close before init ([#23567](vitejs/vite#23567)) ([5f89433](vitejs/vite@5f89433)) - **server:** avoid reinitializing watcher when adding file after server close ([#23572](vitejs/vite#23572)) ([6f831f9](vitejs/vite@6f831f9)) - **sourcemap:** skip URL source roots when injecting sources content ([#23519](vitejs/vite#23519)) ([04fc30a](vitejs/vite@04fc30a)) ##### Miscellaneous Chores - merge prereleases in changelog ([#23466](vitejs/vite#23466)) ([99bd9d1](vitejs/vite@99bd9d1)) - **optimizer:** add debug log when waiting for dep before init ([#23566](vitejs/vite#23566)) ([63567c7](vitejs/vite@63567c7)) - update `optimizeDeps.include` comment ([#23489](vitejs/vite#23489)) ([6a84c72](vitejs/vite@6a84c72)) ##### Code Refactoring - assets regexp use non-capture ([#23491](vitejs/vite#23491)) ([f4b4431](vitejs/vite@f4b4431)) - remove duplicate configurations ([#23532](vitejs/vite#23532)) ([9abd99b](vitejs/vite@9abd99b)) - replace `find` with `some` ([#23554](vitejs/vite#23554)) ([af7cdf6](vitejs/vite@af7cdf6))
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fixes #23696
When the dev client reuses a server-rendered
<style data-vite-dev-id>,updateStylewrites the module's CSS into it even if it's the same text. In Chrome 154 that replaces the stylesheet and re-creates its@font-facerules, the fonts get revalidated, and afont-display: optionalfont that's still loading at render time falls back for good.This only writes when the text is different. HMR updates that change the CSS work as before. One thing that changes: if something edited the stylesheet through the CSSOM, an update with the same text no longer resets it.
For the test I added a
css-stylepage to thehmrplayground, next tocss-link. A small plugin renders the<style data-vite-dev-id>the way an SSR framework would, and a script counts mutations of that style. The test checks that loading the module leaves the style alone (one style, zero mutations) and that editing the file still updates it. Without the fix it gets[1, 1]. Because it counts mutations, it also catches the rewrite in Playwright's Chromium, where the font symptom itself doesn't show.I used an AI assistant while investigating and drafting this. I reviewed the change myself: I read
updateStyleand ran the new test without the fix (fails with[1, 1]) and with it (passes).