Skip to content

Commit 0ec5511

Browse files
authored
Turbopack: fix CSS module references, take 2 (#82448)
Replaces and closes #78058 Closes PACK-4324 Before, you got duplicate modules because `transition_to_client(postcss(webpack(source in rsc)) != postcss(webpack(transition_to_client(source in rsc))` Now, we have: ``` rsc layer --ESM import-> CSSModuleAsset(in rsc, contains raw SCSS source) --CssReferenceSubType::Inner-> CssAsset(first in client layer, then processed with Webpack loader) ``` This aligns it with when you import CSS from a client component, in both cases the CSS module is first transitioned into the client layer, and then processed with Webpack
1 parent 13899e5 commit 0ec5511

File tree

14 files changed

+186
-102
lines changed

14 files changed

+186
-102
lines changed

.github/workflows/build_and_test.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,6 @@ jobs:
314314
export TURBOPACK_BUILD=1
315315
export NEXT_TEST_MODE=start
316316
export NEXT_TEST_REACT_VERSION="${{ matrix.react }}"
317-
# TODO(PACK-4578): Remove
318-
export TURBOPACK_TEMP_DISABLE_DUPLICATE_MODULES_CHECK=1
319317
320318
node run-tests.js --timings -g ${{ matrix.group }} --type production
321319
stepName: 'test-turbopack-production-react-${{ matrix.react }}-${{ matrix.group }}'

crates/next-api/src/app.rs

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use next_core::{
3434
},
3535
next_server_utility::{NEXT_SERVER_UTILITY_MERGE_TAG, NextServerUtilityTransition},
3636
parse_segment_config_from_source,
37-
util::NextRuntime,
37+
util::{NextRuntime, module_styles_rule_condition, styles_rule_condition},
3838
};
3939
use serde::{Deserialize, Serialize};
4040
use tracing::Instrument;
@@ -99,37 +99,6 @@ pub struct AppProject {
9999
pub struct OptionAppProject(Option<ResolvedVc<AppProject>>);
100100

101101
impl AppProject {}
102-
103-
fn styles_rule_condition() -> RuleCondition {
104-
RuleCondition::any(vec![
105-
RuleCondition::all(vec![
106-
RuleCondition::ResourcePathEndsWith(".css".into()),
107-
RuleCondition::not(RuleCondition::ResourcePathEndsWith(".module.css".into())),
108-
]),
109-
RuleCondition::all(vec![
110-
RuleCondition::ResourcePathEndsWith(".scss".into()),
111-
RuleCondition::not(RuleCondition::ResourcePathEndsWith(".module.scss".into())),
112-
]),
113-
RuleCondition::all(vec![
114-
RuleCondition::ResourcePathEndsWith(".sass".into()),
115-
RuleCondition::not(RuleCondition::ResourcePathEndsWith(".module.sass".into())),
116-
]),
117-
RuleCondition::all(vec![
118-
RuleCondition::ContentTypeStartsWith("text/css".into()),
119-
RuleCondition::not(RuleCondition::ContentTypeStartsWith(
120-
"text/css+module".into(),
121-
)),
122-
]),
123-
])
124-
}
125-
fn module_styles_rule_condition() -> RuleCondition {
126-
RuleCondition::any(vec![
127-
RuleCondition::ResourcePathEndsWith(".module.css".into()),
128-
RuleCondition::ResourcePathEndsWith(".module.scss".into()),
129-
RuleCondition::ResourcePathEndsWith(".module.sass".into()),
130-
RuleCondition::ContentTypeStartsWith("text/css+module".into()),
131-
])
132-
}
133102
impl AppProject {
134103
pub fn client_transition_name() -> RcStr {
135104
rcstr!("next-ecmascript-client-reference")
@@ -406,10 +375,10 @@ impl AppProject {
406375
transition_rules: vec![
407376
// Mark as client reference (and exclude from RSC chunking) the edge from the
408377
// CSS Module to the actual CSS
409-
TransitionRule::new_internal(
378+
TransitionRule::new(
410379
RuleCondition::all(vec![
411380
RuleCondition::ReferenceType(ReferenceType::Css(
412-
CssReferenceSubType::Internal,
381+
CssReferenceSubType::Inner,
413382
)),
414383
module_styles_rule_condition(),
415384
]),
@@ -678,6 +647,18 @@ impl AppProject {
678647
Ok(ModuleAssetContext::new(
679648
TransitionOptions {
680649
named_transitions: transitions,
650+
transition_rules: vec![
651+
// Change context, this is used to determine the list of CSS module classes.
652+
TransitionRule::new(
653+
RuleCondition::all(vec![
654+
RuleCondition::ReferenceType(ReferenceType::Css(
655+
CssReferenceSubType::Analyze,
656+
)),
657+
module_styles_rule_condition(),
658+
]),
659+
ResolvedVc::upcast(self.client_transition().to_resolved().await?),
660+
),
661+
],
681662
..Default::default()
682663
}
683664
.cell(),
@@ -738,6 +719,18 @@ impl AppProject {
738719
Ok(ModuleAssetContext::new(
739720
TransitionOptions {
740721
named_transitions: transitions,
722+
transition_rules: vec![
723+
// Change context, this is used to determine the list of CSS module classes.
724+
TransitionRule::new(
725+
RuleCondition::all(vec![
726+
RuleCondition::ReferenceType(ReferenceType::Css(
727+
CssReferenceSubType::Analyze,
728+
)),
729+
module_styles_rule_condition(),
730+
]),
731+
ResolvedVc::upcast(self.client_transition().to_resolved().await?),
732+
),
733+
],
741734
..Default::default()
742735
}
743736
.cell(),

crates/next-core/src/next_client/context.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ use crate::{
6464
get_decorators_transform_options, get_jsx_transform_options,
6565
get_typescript_transform_options,
6666
},
67-
util::{OptionEnvMap, defines, foreign_code_context_condition, internal_assets_conditions},
67+
util::{
68+
OptionEnvMap, defines, foreign_code_context_condition, internal_assets_conditions,
69+
module_styles_rule_condition,
70+
},
6871
};
6972

7073
#[turbo_tasks::function]
@@ -316,6 +319,7 @@ pub async fn get_client_module_options_context(
316319
},
317320
css: CssOptionsContext {
318321
source_maps,
322+
module_css_condition: Some(module_styles_rule_condition()),
319323
..Default::default()
320324
},
321325
environment: Some(env),

crates/next-core/src/next_server/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ use crate::{
7575
util::{
7676
NextRuntime, OptionEnvMap, defines, foreign_code_context_condition,
7777
get_transpiled_packages, internal_assets_conditions, load_next_js_templateon,
78+
module_styles_rule_condition,
7879
},
7980
};
8081

@@ -583,6 +584,7 @@ pub async fn get_server_module_options_context(
583584
environment: Some(environment),
584585
css: CssOptionsContext {
585586
source_maps,
587+
module_css_condition: Some(module_styles_rule_condition()),
586588
..Default::default()
587589
},
588590
tree_shaking_mode: tree_shaking_mode_for_user_code,

crates/next-core/src/next_server/transforms.rs

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use next_custom_transforms::transforms::strip_page_exports::ExportFilter;
33
use turbo_rcstr::RcStr;
44
use turbo_tasks::{ResolvedVc, Vc};
55
use turbopack::module_options::{ModuleRule, ModuleRuleEffect, RuleCondition};
6-
use turbopack_core::reference_type::{ReferenceType, UrlReferenceSubType};
6+
use turbopack_core::reference_type::{CssReferenceSubType, ReferenceType, UrlReferenceSubType};
77

88
use crate::{
99
mode::NextMode,
@@ -21,7 +21,7 @@ use crate::{
2121
next_page_static_info::get_next_page_static_info_assert_rule,
2222
next_pure::get_next_pure_rule, server_actions::ActionsTransform,
2323
},
24-
util::NextRuntime,
24+
util::{NextRuntime, module_styles_rule_condition, styles_rule_condition},
2525
};
2626

2727
/// Returns a list of module rules which apply server-side, Next.js-specific
@@ -51,35 +51,18 @@ pub async fn get_next_server_transforms_rules(
5151

5252
if !matches!(context_ty, ServerContextType::AppRSC { .. }) {
5353
rules.extend([
54-
// Ignore the internal ModuleCssAsset -> CssModuleAsset references
55-
// The CSS Module module itself is still needed for class names
56-
ModuleRule::new_internal(
57-
RuleCondition::any(vec![
58-
RuleCondition::ResourcePathEndsWith(".module.css".into()),
59-
RuleCondition::ContentTypeStartsWith("text/css+module".into()),
60-
]),
61-
vec![ModuleRuleEffect::Ignore],
62-
),
63-
]);
64-
rules.extend([
65-
// Ignore all non-module CSS references
54+
// Ignore the inner ModuleCssAsset -> CssModuleAsset references
55+
// The CSS Module module itself (and the Analyze reference) is still needed to generate
56+
// the class names object.
6657
ModuleRule::new(
67-
RuleCondition::any(vec![
68-
RuleCondition::all(vec![
69-
RuleCondition::ResourcePathEndsWith(".css".into()),
70-
RuleCondition::not(RuleCondition::ResourcePathEndsWith(
71-
".module.css".into(),
72-
)),
73-
]),
74-
RuleCondition::all(vec![
75-
RuleCondition::ContentTypeStartsWith("text/css".into()),
76-
RuleCondition::not(RuleCondition::ContentTypeStartsWith(
77-
"text/css+module".into(),
78-
)),
79-
]),
58+
RuleCondition::all(vec![
59+
RuleCondition::ReferenceType(ReferenceType::Css(CssReferenceSubType::Inner)),
60+
module_styles_rule_condition(),
8061
]),
8162
vec![ModuleRuleEffect::Ignore],
8263
),
64+
// Ignore all non-module CSS references
65+
ModuleRule::new(styles_rule_condition(), vec![ModuleRuleEffect::Ignore]),
8366
]);
8467
}
8568

crates/next-core/src/util.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use turbo_tasks_fs::{
1616
self, File, FileContent, FileSystem, FileSystemPath, json::parse_json_rope_with_source_context,
1717
rope::Rope,
1818
};
19+
use turbopack::module_options::RuleCondition;
1920
use turbopack_core::{
2021
asset::AssetContent,
2122
compile_time_info::{CompileTimeDefineValue, CompileTimeDefines, DefinableNameSegment},
@@ -793,3 +794,48 @@ pub async fn load_next_js_templateon<T: DeserializeOwned>(
793794

794795
Ok(result)
795796
}
797+
798+
pub fn styles_rule_condition() -> RuleCondition {
799+
RuleCondition::any(vec![
800+
RuleCondition::all(vec![
801+
RuleCondition::ResourcePathEndsWith(".css".into()),
802+
RuleCondition::not(RuleCondition::ResourcePathEndsWith(".module.css".into())),
803+
]),
804+
RuleCondition::all(vec![
805+
RuleCondition::ResourcePathEndsWith(".sass".into()),
806+
RuleCondition::not(RuleCondition::ResourcePathEndsWith(".module.sass".into())),
807+
]),
808+
RuleCondition::all(vec![
809+
RuleCondition::ResourcePathEndsWith(".scss".into()),
810+
RuleCondition::not(RuleCondition::ResourcePathEndsWith(".module.scss".into())),
811+
]),
812+
RuleCondition::all(vec![
813+
RuleCondition::ContentTypeStartsWith("text/css".into()),
814+
RuleCondition::not(RuleCondition::ContentTypeStartsWith(
815+
"text/css+module".into(),
816+
)),
817+
]),
818+
RuleCondition::all(vec![
819+
RuleCondition::ContentTypeStartsWith("text/sass".into()),
820+
RuleCondition::not(RuleCondition::ContentTypeStartsWith(
821+
"text/sass+module".into(),
822+
)),
823+
]),
824+
RuleCondition::all(vec![
825+
RuleCondition::ContentTypeStartsWith("text/scss".into()),
826+
RuleCondition::not(RuleCondition::ContentTypeStartsWith(
827+
"text/scss+module".into(),
828+
)),
829+
]),
830+
])
831+
}
832+
pub fn module_styles_rule_condition() -> RuleCondition {
833+
RuleCondition::any(vec![
834+
RuleCondition::ResourcePathEndsWith(".module.css".into()),
835+
RuleCondition::ResourcePathEndsWith(".module.scss".into()),
836+
RuleCondition::ResourcePathEndsWith(".module.sass".into()),
837+
RuleCondition::ContentTypeStartsWith("text/css+module".into()),
838+
RuleCondition::ContentTypeStartsWith("text/sass+module".into()),
839+
RuleCondition::ContentTypeStartsWith("text/scss+module".into()),
840+
])
841+
}

turbopack/crates/turbo-tasks/src/raw_vc.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
use std::{fmt::Display, future::Future, pin::Pin, task::Poll};
1+
use std::{
2+
fmt::{Debug, Display},
3+
future::Future,
4+
pin::Pin,
5+
task::Poll,
6+
};
27

38
use anyhow::Result;
49
use auto_hash_map::AutoSet;
@@ -54,7 +59,7 @@ impl Display for CellId {
5459
/// otherwise be treated as an internal implementation detail of `turbo-tasks`.
5560
///
5661
/// [monomorphization]: https://doc.rust-lang.org/book/ch10-01-syntax.html#performance-of-code-using-generics
57-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
62+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
5863
pub enum RawVc {
5964
/// The synchronous return value of a task (after argument resolution). This is the
6065
/// representation used by [`OperationVc`][crate::OperationVc].
@@ -74,6 +79,28 @@ pub enum RawVc {
7479
LocalOutput(ExecutionId, LocalTaskId, TaskPersistence),
7580
}
7681

82+
impl Debug for RawVc {
83+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84+
match self {
85+
RawVc::TaskOutput(task_id) => f
86+
.debug_tuple("RawVc::TaskOutput")
87+
.field(&**task_id)
88+
.finish(),
89+
RawVc::TaskCell(task_id, cell_id) => f
90+
.debug_tuple("RawVc::TaskCell")
91+
.field(&**task_id)
92+
.field(&cell_id.to_string())
93+
.finish(),
94+
RawVc::LocalOutput(execution_id, local_task_id, task_persistence) => f
95+
.debug_tuple("RawVc::LocalOutput")
96+
.field(&**execution_id)
97+
.field(&**local_task_id)
98+
.field(task_persistence)
99+
.finish(),
100+
}
101+
}
102+
}
103+
77104
impl RawVc {
78105
pub fn is_resolved(&self) -> bool {
79106
match self {

turbopack/crates/turbo-tasks/src/vc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ where
357357
T: ?Sized,
358358
{
359359
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360-
f.debug_struct("Vc").field("node", &self.node).finish()
360+
f.debug_tuple("Vc").field(&self.node).finish()
361361
}
362362
}
363363

turbopack/crates/turbo-tasks/src/vc/resolved.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,7 @@ where
295295
T: ?Sized,
296296
{
297297
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
298-
f.debug_struct("ResolvedVc")
299-
.field("node", &self.node.node)
300-
.finish()
298+
f.debug_tuple("ResolvedVc").field(&self.node.node).finish()
301299
}
302300
}
303301

turbopack/crates/turbopack-core/src/module_graph/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,6 @@ impl SingleModuleGraph {
348348
#[cfg(debug_assertions)]
349349
{
350350
use once_cell::sync::Lazy;
351-
352-
// TODO(PACK-4578): This is temporary while the last issues are being addressed.
353351
static CHECK_FOR_DUPLICATE_MODULES: Lazy<bool> = Lazy::new(|| {
354352
match std::env::var_os("TURBOPACK_TEMP_DISABLE_DUPLICATE_MODULES_CHECK") {
355353
Some(v) => v != "1" && v != "true",

0 commit comments

Comments
 (0)