Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(css): stabilize css module hashes with lightningcss in dev mode #19481

Merged
merged 2 commits into from
Mar 2, 2025

Conversation

azat-io
Copy link
Contributor

@azat-io azat-io commented Feb 21, 2025

Description

Hello!

After upgrading Vite from version 6.0.5 to version 6.0.6 and above, I ran into an issue with hash mismatches in CSS class names in CSS files and in markup.

I found out that the problem is related to this change:
#19001

This PR fixes an issue where CSS module hashes were inconsistent between HTML markup and compiled CSS in development mode when using LightningCSS.

The problem occurred because query parameters (like ?direct) in file IDs were affecting hash generation in LightningCSS. This was particularly noticeable in frameworks like Qwik that use query parameters for direct imports in dev mode.

Fix:

  • Normalize file IDs by removing query parameters before passing to LightningCSS
  • Maintain null byte placeholder replacement for HTML proxy cases

Before the fix:

  • CSS module hashes in HTML could be different from the ones in compiled CSS
  • This caused styling mismatches in development mode
  • The issue was particularly visible with frameworks that use query parameters for imports

After the fix:

  • CSS module hashes are stable and consistent
  • Works correctly with frameworks' development mode imports
  • Maintains compatibility with HTML proxy handling

This fix works for me fine.

If you want to reproduce the problem, you can do the following:

  1. Clone this repo and install deps
  2. Install Vite v6.0.6 or higher
  3. Start dev server with pnpm docs:dev
  4. The site's styles look weird
  5. To fix problem downgrade Vite with pnpm add --save-dev vite@6.0.5 and restart dev server

refs #10514

@azat-io azat-io force-pushed the fix/handle-null-byte-lightningcss branch from 12bb88e to 02d1e07 Compare February 22, 2025 10:51
@azat-io azat-io changed the title fix: handle null byte in module id correctly for lightningcss fix(css): stabilize css module hashes with lightningcss in dev mode Feb 22, 2025
@azat-io
Copy link
Contributor Author

azat-io commented Feb 24, 2025

I think, I should mention here @sapphi-red as the author of this PR and @patak-dev as the reviewer. I'm sorry if I disturbed you.

@sapphi-red sapphi-red added feat: css p3-minor-bug An edge case that only affects very specific usage (priority) labels Feb 25, 2025
Copy link
Member

@sapphi-red sapphi-red left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@patak-dev patak-dev merged commit 92125b4 into vitejs:main Mar 2, 2025
15 checks passed
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Mar 8, 2025
| datasource | package | from  | to    |
| ---------- | ------- | ----- | ----- |
| npm        | vite    | 6.1.0 | 6.2.1 |


## [v6.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small621-2025-03-07-small)

-   refactor: remove `isBuild` check from preAliasPlugin ([#19587](vitejs/vite#19587)) ([c9e086d](vitejs/vite@c9e086d)), closes [#19587](vitejs/vite#19587)
-   refactor: restore endsWith usage ([#19554](vitejs/vite#19554)) ([6113a96](vitejs/vite@6113a96)), closes [#19554](vitejs/vite#19554)
-   refactor: use `applyToEnvironment` in internal plugins ([#19588](vitejs/vite#19588)) ([f678442](vitejs/vite@f678442)), closes [#19588](vitejs/vite#19588)
-   fix(css): stabilize css module hashes with lightningcss in dev mode ([#19481](vitejs/vite#19481)) ([92125b4](vitejs/vite@92125b4)), closes [#19481](vitejs/vite#19481)
-   fix(deps): update all non-major dependencies ([#19555](vitejs/vite#19555)) ([f612e0f](vitejs/vite@f612e0f)), closes [#19555](vitejs/vite#19555)
-   fix(reporter): fix incorrect bundle size calculation with non-ASCII characters ([#19561](vitejs/vite#19561)) ([437c0ed](vitejs/vite@437c0ed)), closes [#19561](vitejs/vite#19561)
-   fix(sourcemap): combine sourcemaps with multiple sources without matched source ([#18971](vitejs/vite#18971)) ([e3f6ae1](vitejs/vite@e3f6ae1)), closes [#18971](vitejs/vite#18971)
-   fix(ssr): named export should overwrite export all ([#19534](vitejs/vite#19534)) ([2fd2fc1](vitejs/vite@2fd2fc1)), closes [#19534](vitejs/vite#19534)
-   feat: add `*?url&no-inline` type and warning for `.json?inline` / `.json?no-inline` ([#19566](vitejs/vite#19566)) ([c0d3667](vitejs/vite@c0d3667)), closes [#19566](vitejs/vite#19566)
-   test: add glob import test case ([#19516](vitejs/vite#19516)) ([aa1d807](vitejs/vite@aa1d807)), closes [#19516](vitejs/vite#19516)
-   test: convert config playground to unit tests ([#19568](vitejs/vite#19568)) ([c0e68da](vitejs/vite@c0e68da)), closes [#19568](vitejs/vite#19568)
-   test: convert resolve-config playground to unit tests ([#19567](vitejs/vite#19567)) ([db5fb48](vitejs/vite@db5fb48)), closes [#19567](vitejs/vite#19567)
-   perf: flush compile cache after 10s ([#19537](vitejs/vite#19537)) ([6c8a5a2](vitejs/vite@6c8a5a2)), closes [#19537](vitejs/vite#19537)
-   chore(css): move environment destructuring after condition check ([#19492](vitejs/vite#19492)) ([c9eda23](vitejs/vite@c9eda23)), closes [#19492](vitejs/vite#19492)
-   chore(html): remove unnecessary value check ([#19491](vitejs/vite#19491)) ([797959f](vitejs/vite@797959f)), closes [#19491](vitejs/vite#19491)


## [v6.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#620-2025-02-25)

-   fix(deps): update all non-major dependencies ([#19501](vitejs/vite#19501)) ([c94c9e0](vitejs/vite@c94c9e0)), closes [#19501](vitejs/vite#19501)
-   fix(worker): string interpolation in dynamic worker options ([#19476](vitejs/vite#19476)) ([07091a1](vitejs/vite@07091a1)), closes [#19476](vitejs/vite#19476)
-   chore: use unicode cross icon instead of x ([#19497](vitejs/vite#19497)) ([5c70296](vitejs/vite@5c70296)), closes [#19497](vitejs/vite#19497)


## [v6.1.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small611-2025-02-19-small)

-   fix: ensure `.[cm]?[tj]sx?` static assets are JS mime ([#19453](vitejs/vite#19453)) ([e7ba55e](vitejs/vite@e7ba55e)), closes [#19453](vitejs/vite#19453)
-   fix: ignore `*.ipv4` address in cert ([#19416](vitejs/vite#19416)) ([973283b](vitejs/vite@973283b)), closes [#19416](vitejs/vite#19416)
-   fix(css): run rewrite plugin if postcss plugin exists ([#19371](vitejs/vite#19371)) ([bcdb51a](vitejs/vite@bcdb51a)), closes [#19371](vitejs/vite#19371)
-   fix(deps): bump tsconfck ([#19375](vitejs/vite#19375)) ([746a583](vitejs/vite@746a583)), closes [#19375](vitejs/vite#19375)
-   fix(deps): update all non-major dependencies ([#19392](vitejs/vite#19392)) ([60456a5](vitejs/vite@60456a5)), closes [#19392](vitejs/vite#19392)
-   fix(deps): update all non-major dependencies ([#19440](vitejs/vite#19440)) ([ccac73d](vitejs/vite@ccac73d)), closes [#19440](vitejs/vite#19440)
-   fix(html): ignore malformed src attrs ([#19397](vitejs/vite#19397)) ([aff7812](vitejs/vite@aff7812)), closes [#19397](vitejs/vite#19397)
-   fix(worker): fix web worker type detection ([#19462](vitejs/vite#19462)) ([edc65ea](vitejs/vite@edc65ea)), closes [#19462](vitejs/vite#19462)
-   refactor: remove custom .jxl mime ([#19457](vitejs/vite#19457)) ([0c85464](vitejs/vite@0c85464)), closes [#19457](vitejs/vite#19457)
-   feat: add support for injecting debug IDs ([#18763](vitejs/vite#18763)) ([0ff556a](vitejs/vite@0ff556a)), closes [#18763](vitejs/vite#18763)
-   chore: update 6.1.0 changelog ([#19363](vitejs/vite#19363)) ([fa7c211](vitejs/vite@fa7c211)), closes [#19363](vitejs/vite#19363)
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Mar 8, 2025
| datasource | package | from  | to    |
| ---------- | ------- | ----- | ----- |
| npm        | vite    | 6.1.0 | 6.2.1 |


## [v6.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small621-2025-03-07-small)

-   refactor: remove `isBuild` check from preAliasPlugin ([#19587](vitejs/vite#19587)) ([c9e086d](vitejs/vite@c9e086d)), closes [#19587](vitejs/vite#19587)
-   refactor: restore endsWith usage ([#19554](vitejs/vite#19554)) ([6113a96](vitejs/vite@6113a96)), closes [#19554](vitejs/vite#19554)
-   refactor: use `applyToEnvironment` in internal plugins ([#19588](vitejs/vite#19588)) ([f678442](vitejs/vite@f678442)), closes [#19588](vitejs/vite#19588)
-   fix(css): stabilize css module hashes with lightningcss in dev mode ([#19481](vitejs/vite#19481)) ([92125b4](vitejs/vite@92125b4)), closes [#19481](vitejs/vite#19481)
-   fix(deps): update all non-major dependencies ([#19555](vitejs/vite#19555)) ([f612e0f](vitejs/vite@f612e0f)), closes [#19555](vitejs/vite#19555)
-   fix(reporter): fix incorrect bundle size calculation with non-ASCII characters ([#19561](vitejs/vite#19561)) ([437c0ed](vitejs/vite@437c0ed)), closes [#19561](vitejs/vite#19561)
-   fix(sourcemap): combine sourcemaps with multiple sources without matched source ([#18971](vitejs/vite#18971)) ([e3f6ae1](vitejs/vite@e3f6ae1)), closes [#18971](vitejs/vite#18971)
-   fix(ssr): named export should overwrite export all ([#19534](vitejs/vite#19534)) ([2fd2fc1](vitejs/vite@2fd2fc1)), closes [#19534](vitejs/vite#19534)
-   feat: add `*?url&no-inline` type and warning for `.json?inline` / `.json?no-inline` ([#19566](vitejs/vite#19566)) ([c0d3667](vitejs/vite@c0d3667)), closes [#19566](vitejs/vite#19566)
-   test: add glob import test case ([#19516](vitejs/vite#19516)) ([aa1d807](vitejs/vite@aa1d807)), closes [#19516](vitejs/vite#19516)
-   test: convert config playground to unit tests ([#19568](vitejs/vite#19568)) ([c0e68da](vitejs/vite@c0e68da)), closes [#19568](vitejs/vite#19568)
-   test: convert resolve-config playground to unit tests ([#19567](vitejs/vite#19567)) ([db5fb48](vitejs/vite@db5fb48)), closes [#19567](vitejs/vite#19567)
-   perf: flush compile cache after 10s ([#19537](vitejs/vite#19537)) ([6c8a5a2](vitejs/vite@6c8a5a2)), closes [#19537](vitejs/vite#19537)
-   chore(css): move environment destructuring after condition check ([#19492](vitejs/vite#19492)) ([c9eda23](vitejs/vite@c9eda23)), closes [#19492](vitejs/vite#19492)
-   chore(html): remove unnecessary value check ([#19491](vitejs/vite#19491)) ([797959f](vitejs/vite@797959f)), closes [#19491](vitejs/vite#19491)


## [v6.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#620-2025-02-25)

-   fix(deps): update all non-major dependencies ([#19501](vitejs/vite#19501)) ([c94c9e0](vitejs/vite@c94c9e0)), closes [#19501](vitejs/vite#19501)
-   fix(worker): string interpolation in dynamic worker options ([#19476](vitejs/vite#19476)) ([07091a1](vitejs/vite@07091a1)), closes [#19476](vitejs/vite#19476)
-   chore: use unicode cross icon instead of x ([#19497](vitejs/vite#19497)) ([5c70296](vitejs/vite@5c70296)), closes [#19497](vitejs/vite#19497)


## [v6.1.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small611-2025-02-19-small)

-   fix: ensure `.[cm]?[tj]sx?` static assets are JS mime ([#19453](vitejs/vite#19453)) ([e7ba55e](vitejs/vite@e7ba55e)), closes [#19453](vitejs/vite#19453)
-   fix: ignore `*.ipv4` address in cert ([#19416](vitejs/vite#19416)) ([973283b](vitejs/vite@973283b)), closes [#19416](vitejs/vite#19416)
-   fix(css): run rewrite plugin if postcss plugin exists ([#19371](vitejs/vite#19371)) ([bcdb51a](vitejs/vite@bcdb51a)), closes [#19371](vitejs/vite#19371)
-   fix(deps): bump tsconfck ([#19375](vitejs/vite#19375)) ([746a583](vitejs/vite@746a583)), closes [#19375](vitejs/vite#19375)
-   fix(deps): update all non-major dependencies ([#19392](vitejs/vite#19392)) ([60456a5](vitejs/vite@60456a5)), closes [#19392](vitejs/vite#19392)
-   fix(deps): update all non-major dependencies ([#19440](vitejs/vite#19440)) ([ccac73d](vitejs/vite@ccac73d)), closes [#19440](vitejs/vite#19440)
-   fix(html): ignore malformed src attrs ([#19397](vitejs/vite#19397)) ([aff7812](vitejs/vite@aff7812)), closes [#19397](vitejs/vite#19397)
-   fix(worker): fix web worker type detection ([#19462](vitejs/vite#19462)) ([edc65ea](vitejs/vite@edc65ea)), closes [#19462](vitejs/vite#19462)
-   refactor: remove custom .jxl mime ([#19457](vitejs/vite#19457)) ([0c85464](vitejs/vite@0c85464)), closes [#19457](vitejs/vite#19457)
-   feat: add support for injecting debug IDs ([#18763](vitejs/vite#18763)) ([0ff556a](vitejs/vite@0ff556a)), closes [#18763](vitejs/vite#18763)
-   chore: update 6.1.0 changelog ([#19363](vitejs/vite#19363)) ([fa7c211](vitejs/vite@fa7c211)), closes [#19363](vitejs/vite#19363)
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Mar 9, 2025
| datasource | package | from  | to    |
| ---------- | ------- | ----- | ----- |
| npm        | vite    | 6.1.0 | 6.2.1 |


## [v6.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small621-2025-03-07-small)

-   refactor: remove `isBuild` check from preAliasPlugin ([#19587](vitejs/vite#19587)) ([c9e086d](vitejs/vite@c9e086d)), closes [#19587](vitejs/vite#19587)
-   refactor: restore endsWith usage ([#19554](vitejs/vite#19554)) ([6113a96](vitejs/vite@6113a96)), closes [#19554](vitejs/vite#19554)
-   refactor: use `applyToEnvironment` in internal plugins ([#19588](vitejs/vite#19588)) ([f678442](vitejs/vite@f678442)), closes [#19588](vitejs/vite#19588)
-   fix(css): stabilize css module hashes with lightningcss in dev mode ([#19481](vitejs/vite#19481)) ([92125b4](vitejs/vite@92125b4)), closes [#19481](vitejs/vite#19481)
-   fix(deps): update all non-major dependencies ([#19555](vitejs/vite#19555)) ([f612e0f](vitejs/vite@f612e0f)), closes [#19555](vitejs/vite#19555)
-   fix(reporter): fix incorrect bundle size calculation with non-ASCII characters ([#19561](vitejs/vite#19561)) ([437c0ed](vitejs/vite@437c0ed)), closes [#19561](vitejs/vite#19561)
-   fix(sourcemap): combine sourcemaps with multiple sources without matched source ([#18971](vitejs/vite#18971)) ([e3f6ae1](vitejs/vite@e3f6ae1)), closes [#18971](vitejs/vite#18971)
-   fix(ssr): named export should overwrite export all ([#19534](vitejs/vite#19534)) ([2fd2fc1](vitejs/vite@2fd2fc1)), closes [#19534](vitejs/vite#19534)
-   feat: add `*?url&no-inline` type and warning for `.json?inline` / `.json?no-inline` ([#19566](vitejs/vite#19566)) ([c0d3667](vitejs/vite@c0d3667)), closes [#19566](vitejs/vite#19566)
-   test: add glob import test case ([#19516](vitejs/vite#19516)) ([aa1d807](vitejs/vite@aa1d807)), closes [#19516](vitejs/vite#19516)
-   test: convert config playground to unit tests ([#19568](vitejs/vite#19568)) ([c0e68da](vitejs/vite@c0e68da)), closes [#19568](vitejs/vite#19568)
-   test: convert resolve-config playground to unit tests ([#19567](vitejs/vite#19567)) ([db5fb48](vitejs/vite@db5fb48)), closes [#19567](vitejs/vite#19567)
-   perf: flush compile cache after 10s ([#19537](vitejs/vite#19537)) ([6c8a5a2](vitejs/vite@6c8a5a2)), closes [#19537](vitejs/vite#19537)
-   chore(css): move environment destructuring after condition check ([#19492](vitejs/vite#19492)) ([c9eda23](vitejs/vite@c9eda23)), closes [#19492](vitejs/vite#19492)
-   chore(html): remove unnecessary value check ([#19491](vitejs/vite#19491)) ([797959f](vitejs/vite@797959f)), closes [#19491](vitejs/vite#19491)


## [v6.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#620-2025-02-25)

-   fix(deps): update all non-major dependencies ([#19501](vitejs/vite#19501)) ([c94c9e0](vitejs/vite@c94c9e0)), closes [#19501](vitejs/vite#19501)
-   fix(worker): string interpolation in dynamic worker options ([#19476](vitejs/vite#19476)) ([07091a1](vitejs/vite@07091a1)), closes [#19476](vitejs/vite#19476)
-   chore: use unicode cross icon instead of x ([#19497](vitejs/vite#19497)) ([5c70296](vitejs/vite@5c70296)), closes [#19497](vitejs/vite#19497)


## [v6.1.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small611-2025-02-19-small)

-   fix: ensure `.[cm]?[tj]sx?` static assets are JS mime ([#19453](vitejs/vite#19453)) ([e7ba55e](vitejs/vite@e7ba55e)), closes [#19453](vitejs/vite#19453)
-   fix: ignore `*.ipv4` address in cert ([#19416](vitejs/vite#19416)) ([973283b](vitejs/vite@973283b)), closes [#19416](vitejs/vite#19416)
-   fix(css): run rewrite plugin if postcss plugin exists ([#19371](vitejs/vite#19371)) ([bcdb51a](vitejs/vite@bcdb51a)), closes [#19371](vitejs/vite#19371)
-   fix(deps): bump tsconfck ([#19375](vitejs/vite#19375)) ([746a583](vitejs/vite@746a583)), closes [#19375](vitejs/vite#19375)
-   fix(deps): update all non-major dependencies ([#19392](vitejs/vite#19392)) ([60456a5](vitejs/vite@60456a5)), closes [#19392](vitejs/vite#19392)
-   fix(deps): update all non-major dependencies ([#19440](vitejs/vite#19440)) ([ccac73d](vitejs/vite@ccac73d)), closes [#19440](vitejs/vite#19440)
-   fix(html): ignore malformed src attrs ([#19397](vitejs/vite#19397)) ([aff7812](vitejs/vite@aff7812)), closes [#19397](vitejs/vite#19397)
-   fix(worker): fix web worker type detection ([#19462](vitejs/vite#19462)) ([edc65ea](vitejs/vite@edc65ea)), closes [#19462](vitejs/vite#19462)
-   refactor: remove custom .jxl mime ([#19457](vitejs/vite#19457)) ([0c85464](vitejs/vite@0c85464)), closes [#19457](vitejs/vite#19457)
-   feat: add support for injecting debug IDs ([#18763](vitejs/vite#18763)) ([0ff556a](vitejs/vite@0ff556a)), closes [#18763](vitejs/vite#18763)
-   chore: update 6.1.0 changelog ([#19363](vitejs/vite#19363)) ([fa7c211](vitejs/vite@fa7c211)), closes [#19363](vitejs/vite#19363)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: css p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants