Skip to content

Commit 6cf4019

Browse files
authored
fix(css): include local name in hash-only local idents (#14334)
* fix(css): include local name in hash-only local idents * docs(css): clarify local ident hash behavior
1 parent 1fd4fca commit 6cf4019

6 files changed

Lines changed: 73 additions & 59 deletions

File tree

crates/rspack_plugin_css/src/utils.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,21 @@ impl<'a> LocalIdentOptions<'a> {
240240
.and_then(|s| s.to_str())
241241
.unwrap_or_default();
242242
let id = PathData::prepare_id(CSS_MODULE_ID_PLACEHOLDER);
243+
let hash = if self
244+
.local_ident_name
245+
.template
246+
.template()
247+
.is_some_and(|template| template.contains("[local]"))
248+
{
249+
self.module_hash(module_hash_options)
250+
} else {
251+
local_ident_hash.as_str()
252+
};
243253
let local_ident = LocalIdentNameRenderOptions {
244254
path_data: PathData::default()
245255
.filename(&self.relative_resource)
246256
.chunk_name(chunk_name)
247-
.hash(self.module_hash(module_hash_options))
257+
.hash(hash)
248258
.content_hash(content_hash)
249259
.id(id.as_ref()),
250260
local,
Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,50 @@
11
Object {
2-
#: _23c95c53278a334f,
3-
##: _23c95c53278a334f,
4-
#.#.#: _23c95c53278a334f,
5-
#fake-id: _23c95c53278a334f,
6-
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.: _23c95c53278a334f,
7-
-a-b-c-: _23c95c53278a334f,
8-
-a0-34a___f: _23c95c53278a334f,
9-
.: _23c95c53278a334f,
10-
123: _23c95c53278a334f,
11-
1a2b3c: _23c95c53278a334f,
12-
:): _23c95c53278a334f,
13-
:`(: _23c95c53278a334f,
14-
:hover: _23c95c53278a334f,
15-
:hover:focus:active: _23c95c53278a334f,
16-
<><<<>><>: _23c95c53278a334f,
17-
<p>: _23c95c53278a334f,
18-
?: _23c95c53278a334f,
19-
@: _23c95c53278a334f,
20-
B&W?: _23c95c53278a334f,
21-
[attr=value]: _23c95c53278a334f,
22-
_: _23c95c53278a334f,
23-
_test: _23c95c53278a334f,
24-
className: _23c95c53278a334f,
25-
f!o!o: _23c95c53278a334f,
26-
f'o'o: _23c95c53278a334f,
27-
f*o*o: _23c95c53278a334f,
28-
f+o+o: _23c95c53278a334f,
29-
f/o/o: _23c95c53278a334f,
30-
f\o\o: _23c95c53278a334f,
31-
foo.bar: _23c95c53278a334f,
32-
foo/bar: _23c95c53278a334f,
33-
foo/bar/baz: _23c95c53278a334f,
34-
foo\bar: _23c95c53278a334f,
35-
foo\bar\baz: _23c95c53278a334f,
36-
f~o~o: _23c95c53278a334f,
37-
m_x_@: _23c95c53278a334f,
38-
someId: _23c95c53278a334f,
39-
subClass: _23c95c53278a334f,
40-
test: _23c95c53278a334f,
41-
{}: _23c95c53278a334f,
42-
©: _23c95c53278a334f,
43-
“‘’”: _23c95c53278a334f,
44-
⌘⌥: _23c95c53278a334f,
45-
☺☃: _23c95c53278a334f,
46-
♥: _23c95c53278a334f,
47-
𝄞♪♩♫♬: _23c95c53278a334f,
48-
💩: _23c95c53278a334f,
49-
😍: _23c95c53278a334f,
2+
#: ab5b3430521fed0b,
3+
##: _94cb547534b9bb8e,
4+
#.#.#: _8a4c570203a26b7a,
5+
#fake-id: _48f7b6eb7b0e0c18,
6+
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.: c40d0c7abfea21c2,
7+
-a-b-c-: _41b1d2002fed1364,
8+
-a0-34a___f: _76004bd6992764ef,
9+
.: _562aba9a87983bb4,
10+
123: _44fc0eed74768cf0,
11+
1a2b3c: _45189cd4a1680594,
12+
:): f173228435cfb0b1,
13+
:`(: _2c028ead51dd2190,
14+
:hover: _4bcf55b240a0c8c3,
15+
:hover:focus:active: a9b6b582b414966b,
16+
<><<<>><>: _2c75f56ad7787952,
17+
<p>: aeefcae4950d33f5,
18+
?: _5e40713fc7c65c3f,
19+
@: _81cd391b9e31254d,
20+
B&W?: _8daaf197c50aa167,
21+
[attr=value]: _64fa72982cc3b312,
22+
_: _7814922bd050c4fe,
23+
_test: _4011f95d7802389a,
24+
className: _8b88ec9c3ddaa088,
25+
f!o!o: _6ae3ae8c7841a7dc,
26+
f'o'o: _1df77f78fe66aae2,
27+
f*o*o: a7fec00e3ce42886,
28+
f+o+o: _6eb6cf0061b2d78e,
29+
f/o/o: d0e703c722b26d0c,
30+
f\o\o: a496c6306a14d13d,
31+
foo.bar: cd2e4302e8b6edf3,
32+
foo/bar: _7cd90db0f2125295,
33+
foo/bar/baz: f253f688730bc76e,
34+
foo\bar: _47141eb2a9acb231,
35+
foo\bar\baz: b41adbd8ba363134,
36+
f~o~o: _104b5f0b0aac1e4e,
37+
m_x_@: deacd91fcb5633e3,
38+
someId: f39bfe4a4606a57c,
39+
subClass: dbb85e97d7af8a70,
40+
test: db0a8ac9537cb87c,
41+
{}: _0b674276dd02fd15,
42+
©: _4721925fc4038317,
43+
“‘’”: _6295b1f8cf023766,
44+
⌘⌥: _5464233501cad802,
45+
☺☃: _8a5266303d99e4a3,
46+
♥: _8573640b3f2fd830,
47+
𝄞♪♩♫♬: c573deb3b242a81b,
48+
💩: _0f17b76fb4694950,
49+
😍: _5653d57d2641b441,
5050
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Object {
2-
btn--info_is-disabled_1: _39a03a7331600c566ada,
3-
btn-info_is-disabled: _39a03a7331600c566ada,
4-
color-red: --_39a03a7331600c566ada,
2+
btn--info_is-disabled_1: _2058b663514f2425ba48,
3+
btn-info_is-disabled: _2aba8b96a0ac031f537a,
4+
color-red: --_0de89cac8a4c2f23ed3a,
55
foo: bar,
6-
foo_bar: _39a03a7331600c566ada,
6+
foo_bar: _7d728a7a17547f118b8f,
77
my-btn-info_is-disabled: value,
8-
simple: _39a03a7331600c566ada,
8+
simple: _0536cc02142c55d85df9,
99
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Object {
2-
btn--info_is-disabled_1: b9b3b0d9b3a9dad9c607,
3-
btn-info_is-disabled: b9b3b0d9b3a9dad9c607,
4-
color-red: --b9b3b0d9b3a9dad9c607,
2+
btn--info_is-disabled_1: _2058b663514f2425ba48,
3+
btn-info_is-disabled: _2aba8b96a0ac031f537a,
4+
color-red: --_0de89cac8a4c2f23ed3a,
55
foo: bar,
6-
foo_bar: b9b3b0d9b3a9dad9c607,
6+
foo_bar: _7d728a7a17547f118b8f,
77
my-btn-info_is-disabled: value,
8-
simple: b9b3b0d9b3a9dad9c607,
8+
simple: _0536cc02142c55d85df9,
99
}

website/docs/en/config/module-generator.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,8 @@ export default {
596596
597597
Customize the format of the local class names generated for CSS modules, besides the substitutions at [File-level](/config/filename-placeholders#file-placeholders) and [Module-level](/config/filename-placeholders#module-placeholders), also include `[uniqueName]` and `[local]`.
598598
599+
Starting from Rspack `2.0.7`, the `[hash]` placeholder in `localIdentName` uses different hash inputs depending on whether the template includes `[local]`. When `localIdentName` does not include `[local]`, the local name is included in the hash input so different local names in the same CSS module generate different values. When `localIdentName` includes `[local]`, the local name is not included in the `[hash]` input because `[local]` already keeps the generated class name unique.
600+
599601
```js title="rspack.config.mjs"
600602
export default {
601603
module: {

website/docs/zh/config/module-generator.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,8 @@ export default {
595595
596596
自定义生成的 CSS Modules 的局部类名格式,除了在[文件级别](/config/filename-placeholders#file-占位符)和[模块级别](/config/filename-placeholders#module-占位符)的替换之外,还包括 `[uniqueName]``[local]`
597597
598+
从 Rspack `2.0.7` 开始,`localIdentName` 中的 `[hash]` 占位符会根据模板中是否包含 `[local]` 使用不同的哈希输入。当 `localIdentName` 不包含 `[local]` 时,局部类名会作为哈希输入的一部分,因此同一个 CSS Module 中不同的局部类名会生成不同的值。当 `localIdentName` 包含 `[local]` 时,局部类名不会再作为 `[hash]` 的输入,因为 `[local]` 已经能保证最终生成的类名唯一。
599+
598600
```js title="rspack.config.mjs"
599601
export default {
600602
module: {

0 commit comments

Comments
 (0)