Skip to content

Commit 7b30107

Browse files
authored
Turbopack: refactor CssEmbed to avoid creating a chunk item (#77303)
### What? refactor CssEmbed to avoid creating a chunk item which writes only a comment to a output file To do that we export references from css where static assets are embedded into
1 parent fc03ca7 commit 7b30107

15 files changed

+274
-324
lines changed

test/integration/css/test/basic-global-support.test.js

+210-153
Large diffs are not rendered by default.

turbopack/crates/turbopack-css/src/asset.rs

+22-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use turbopack_core::{
99
ident::AssetIdent,
1010
module::Module,
1111
module_graph::ModuleGraph,
12+
output::OutputAssets,
1213
reference::{ModuleReference, ModuleReferences},
1314
reference_type::ImportContext,
1415
resolve::origin::ResolveOrigin,
@@ -22,7 +23,9 @@ use crate::{
2223
finalize_css, parse_css, process_css_with_placeholder, CssWithPlaceholderResult,
2324
FinalCssResult, ParseCss, ParseCssResult, ProcessCss,
2425
},
25-
references::{compose::CssModuleComposeReference, import::ImportAssetReference},
26+
references::{
27+
compose::CssModuleComposeReference, import::ImportAssetReference, url::ReferencedAsset,
28+
},
2629
CssModuleAssetType,
2730
};
2831

@@ -95,13 +98,12 @@ impl ProcessCss for CssModuleAsset {
9598
#[turbo_tasks::function]
9699
fn finalize_css(
97100
self: Vc<Self>,
98-
module_graph: Vc<ModuleGraph>,
99101
chunking_context: Vc<Box<dyn ChunkingContext>>,
100102
minify_type: MinifyType,
101103
) -> Vc<FinalCssResult> {
102104
let process_result = self.get_css_with_placeholder();
103105

104-
finalize_css(process_result, module_graph, chunking_context, minify_type)
106+
finalize_css(process_result, chunking_context, minify_type)
105107
}
106108
}
107109

@@ -201,6 +203,22 @@ impl ChunkItem for CssModuleChunkItem {
201203
fn module(&self) -> Vc<Box<dyn Module>> {
202204
Vc::upcast(*self.module)
203205
}
206+
207+
#[turbo_tasks::function]
208+
async fn references(&self) -> Result<Vc<OutputAssets>> {
209+
let mut references = Vec::new();
210+
if let ParseCssResult::Ok { url_references, .. } = &*self.module.parse_css().await? {
211+
for (_, reference) in url_references.await? {
212+
if let ReferencedAsset::Some(asset) = *reference
213+
.get_referenced_asset(*self.chunking_context)
214+
.await?
215+
{
216+
references.push(asset);
217+
}
218+
}
219+
}
220+
Ok(Vc::cell(references))
221+
}
204222
}
205223

206224
#[turbo_tasks::value_impl]
@@ -280,11 +298,7 @@ impl CssChunkItem for CssModuleChunkItem {
280298

281299
let result = self
282300
.module
283-
.finalize_css(
284-
*self.module_graph,
285-
*chunking_context,
286-
self.module.await?.minify_type,
287-
)
301+
.finalize_css(*chunking_context, self.module.await?.minify_type)
288302
.await?;
289303

290304
if let FinalCssResult::Ok {
+6-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use turbo_tasks::Vc;
2-
use turbopack_core::{chunk::ChunkItem, output::OutputAsset};
2+
use turbopack_core::{asset::Asset, chunk::ChunkingContext, module::Module, output::OutputAsset};
33

44
#[turbo_tasks::value_trait]
5-
pub trait CssEmbed: ChunkItem {
6-
fn embedded_asset(self: Vc<Self>) -> Vc<Box<dyn OutputAsset>>;
5+
pub trait CssEmbed: Module + Asset {
6+
fn embedded_asset(
7+
self: Vc<Self>,
8+
chunking_context: Vc<Box<dyn ChunkingContext>>,
9+
) -> Vc<Box<dyn OutputAsset>>;
710
}

turbopack/crates/turbopack-css/src/process.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use turbopack_core::{
2323
Issue, IssueExt, IssueSource, IssueStage, OptionIssueSource, OptionStyledString,
2424
StyledString,
2525
},
26-
module_graph::ModuleGraph,
2726
reference::ModuleReferences,
2827
reference_type::ImportContext,
2928
resolve::origin::ResolveOrigin,
@@ -220,7 +219,6 @@ pub async fn process_css_with_placeholder(
220219
#[turbo_tasks::function]
221220
pub async fn finalize_css(
222221
result: Vc<CssWithPlaceholderResult>,
223-
module_graph: Vc<ModuleGraph>,
224222
chunking_context: Vc<Box<dyn ChunkingContext>>,
225223
minify_type: MinifyType,
226224
) -> Result<Vc<FinalCssResult>> {
@@ -247,8 +245,7 @@ pub async fn finalize_css(
247245
let mut url_map = FxHashMap::default();
248246

249247
for (src, reference) in (*url_references.await?).iter() {
250-
let resolved =
251-
resolve_url_reference(**reference, module_graph, chunking_context).await?;
248+
let resolved = resolve_url_reference(**reference, chunking_context).await?;
252249
if let Some(v) = resolved.as_ref().cloned() {
253250
url_map.insert(RcStr::from(src.as_str()), v);
254251
}
@@ -286,7 +283,6 @@ pub trait ProcessCss: ParseCss {
286283

287284
async fn finalize_css(
288285
self: Vc<Self>,
289-
module_graph: Vc<ModuleGraph>,
290286
chunking_context: Vc<Box<dyn ChunkingContext>>,
291287
minify_type: MinifyType,
292288
) -> Result<Vc<FinalCssResult>>;

turbopack/crates/turbopack-css/src/references/url.rs

+14-26
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
use std::convert::Infallible;
22

3-
use anyhow::{bail, Result};
3+
use anyhow::Result;
44
use lightningcss::{
55
values::url::Url,
66
visit_types,
77
visitor::{Visit, Visitor},
88
};
99
use rustc_hash::FxHashMap;
1010
use turbo_rcstr::RcStr;
11-
use turbo_tasks::{debug::ValueDebug, ResolvedVc, Value, ValueToString, Vc};
11+
use turbo_tasks::{ResolvedVc, Value, ValueToString, Vc};
1212
use turbopack_core::{
13-
chunk::{ChunkableModule, ChunkableModuleReference, ChunkingContext},
13+
chunk::{ChunkableModuleReference, ChunkingContext},
1414
ident::AssetIdent,
1515
issue::IssueSource,
16-
module_graph::ModuleGraph,
1716
output::OutputAsset,
1817
reference::ModuleReference,
1918
reference_type::{ReferenceType, UrlReferenceSubType},
@@ -52,28 +51,21 @@ impl UrlAssetReference {
5251
}
5352

5453
#[turbo_tasks::function]
55-
async fn get_referenced_asset(
54+
pub async fn get_referenced_asset(
5655
self: Vc<Self>,
57-
module_graph: Vc<ModuleGraph>,
5856
chunking_context: Vc<Box<dyn ChunkingContext>>,
5957
) -> Result<Vc<ReferencedAsset>> {
6058
if let Some(module) = *self.resolve_reference().first_module().await? {
61-
if let Some(chunkable) = ResolvedVc::try_downcast::<Box<dyn ChunkableModule>>(module) {
62-
let chunk_item = chunkable.as_chunk_item(module_graph, chunking_context);
63-
if let Some(embeddable) =
64-
Vc::try_resolve_downcast::<Box<dyn CssEmbed>>(chunk_item).await?
65-
{
66-
return Ok(ReferencedAsset::Some(
67-
embeddable.embedded_asset().to_resolved().await?,
68-
)
69-
.into());
70-
}
59+
if let Some(embeddable) = Vc::try_resolve_downcast::<Box<dyn CssEmbed>>(*module).await?
60+
{
61+
return Ok(ReferencedAsset::Some(
62+
embeddable
63+
.embedded_asset(chunking_context)
64+
.to_resolved()
65+
.await?,
66+
)
67+
.into());
7168
}
72-
bail!(
73-
"A module referenced by a url() reference must be chunkable and the chunk item \
74-
must be css embeddable\nreferenced module: {:?}",
75-
module.dbg_depth(1).await?
76-
)
7769
}
7870
Ok(ReferencedAsset::cell(ReferencedAsset::None))
7971
}
@@ -109,7 +101,6 @@ impl ValueToString for UrlAssetReference {
109101
#[turbo_tasks::function]
110102
pub async fn resolve_url_reference(
111103
url: Vc<UrlAssetReference>,
112-
module_graph: Vc<ModuleGraph>,
113104
chunking_context: Vc<Box<dyn ChunkingContext>>,
114105
) -> Result<Vc<Option<RcStr>>> {
115106
let this = url.await?;
@@ -121,10 +112,7 @@ pub async fn resolve_url_reference(
121112
);
122113
let context_path = chunk_path.parent().await?;
123114

124-
if let ReferencedAsset::Some(asset) = &*url
125-
.get_referenced_asset(module_graph, chunking_context)
126-
.await?
127-
{
115+
if let ReferencedAsset::Some(asset) = &*url.get_referenced_asset(chunking_context).await? {
128116
// TODO(WEB-662) This is not the correct way to get the path of the asset.
129117
// `asset` is on module-level, but we need the output-level asset instead.
130118
let path = asset.path().await?;

turbopack/crates/turbopack-static/src/css.rs

+9-107
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1-
use anyhow::Result;
21
use turbo_rcstr::RcStr;
32
use turbo_tasks::{ResolvedVc, Vc};
43
use turbopack_core::{
54
asset::{Asset, AssetContent},
6-
chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkingContext},
5+
chunk::ChunkingContext,
76
ident::AssetIdent,
87
module::Module,
9-
module_graph::ModuleGraph,
10-
output::{OutputAsset, OutputAssets},
8+
output::OutputAsset,
119
source::Source,
1210
};
13-
use turbopack_css::{
14-
chunk::{CssChunkItem, CssChunkItemContent, CssChunkType},
15-
embed::CssEmbed,
16-
};
17-
use turbopack_ecmascript::{
18-
chunk::{EcmascriptChunkPlaceable, EcmascriptExports},
19-
utils::StringifyJs,
20-
};
11+
use turbopack_css::embed::CssEmbed;
2112

2213
use crate::output_asset::StaticOutputAsset;
2314

@@ -65,102 +56,13 @@ impl Asset for StaticUrlCssModule {
6556
}
6657

6758
#[turbo_tasks::value_impl]
68-
impl ChunkableModule for StaticUrlCssModule {
69-
#[turbo_tasks::function]
70-
async fn as_chunk_item(
71-
self: ResolvedVc<Self>,
72-
_module_graph: Vc<ModuleGraph>,
73-
chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
74-
) -> Result<Vc<Box<dyn turbopack_core::chunk::ChunkItem>>> {
75-
Ok(Vc::upcast(StaticUrlCssChunkItem::cell(
76-
StaticUrlCssChunkItem {
77-
module: self,
78-
chunking_context,
79-
static_asset: self
80-
.static_output_asset(*ResolvedVc::upcast(chunking_context))
81-
.to_resolved()
82-
.await?,
83-
},
84-
)))
85-
}
86-
}
87-
88-
#[turbo_tasks::value_impl]
89-
impl EcmascriptChunkPlaceable for StaticUrlCssModule {
90-
#[turbo_tasks::function]
91-
fn get_exports(&self) -> Vc<EcmascriptExports> {
92-
EcmascriptExports::Value.into()
93-
}
94-
}
95-
96-
#[turbo_tasks::value]
97-
struct StaticUrlCssChunkItem {
98-
module: ResolvedVc<StaticUrlCssModule>,
99-
chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
100-
static_asset: ResolvedVc<StaticOutputAsset>,
101-
}
102-
103-
#[turbo_tasks::value_impl]
104-
impl ChunkItem for StaticUrlCssChunkItem {
105-
#[turbo_tasks::function]
106-
fn asset_ident(&self) -> Vc<AssetIdent> {
107-
self.module.ident()
108-
}
109-
110-
#[turbo_tasks::function]
111-
fn references(&self) -> Vc<OutputAssets> {
112-
Vc::cell(vec![ResolvedVc::upcast(self.static_asset)])
113-
}
114-
115-
#[turbo_tasks::function]
116-
fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
117-
*ResolvedVc::upcast(self.chunking_context)
118-
}
119-
120-
#[turbo_tasks::function]
121-
async fn ty(&self) -> Result<Vc<Box<dyn ChunkType>>> {
122-
Ok(Vc::upcast(Vc::<CssChunkType>::default().resolve().await?))
123-
}
124-
125-
#[turbo_tasks::function]
126-
fn module(&self) -> Vc<Box<dyn Module>> {
127-
*ResolvedVc::upcast(self.module)
128-
}
129-
}
130-
131-
#[turbo_tasks::value_impl]
132-
impl CssChunkItem for StaticUrlCssChunkItem {
133-
#[turbo_tasks::function]
134-
fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
135-
*self.chunking_context
136-
}
137-
138-
#[turbo_tasks::function]
139-
async fn content(&self) -> Result<Vc<CssChunkItemContent>> {
140-
Ok(CssChunkItemContent {
141-
import_context: None,
142-
imports: Vec::new(),
143-
source_map: None,
144-
inner_code: format!(
145-
"/* embedded static asset {path} */",
146-
path = StringifyJs(
147-
&self
148-
.chunking_context
149-
.asset_url(self.static_asset.path())
150-
.await?
151-
)
152-
)
153-
.into(),
154-
}
155-
.into())
156-
}
157-
}
158-
159-
#[turbo_tasks::value_impl]
160-
impl CssEmbed for StaticUrlCssChunkItem {
59+
impl CssEmbed for StaticUrlCssModule {
16160
#[turbo_tasks::function]
162-
fn embedded_asset(&self) -> Vc<Box<dyn OutputAsset>> {
163-
*ResolvedVc::upcast(self.static_asset)
61+
fn embedded_asset(
62+
self: Vc<Self>,
63+
chunking_context: Vc<Box<dyn ChunkingContext>>,
64+
) -> Vc<Box<dyn OutputAsset>> {
65+
Vc::upcast(self.static_output_asset(chunking_context))
16466
}
16567
}
16668

turbopack/crates/turbopack-tests/tests/snapshot/css/embed-url/output/4e721_crates_turbopack-tests_tests_snapshot_css_embed-url_input_image_png_ba3284f5._.single.css

-2
This file was deleted.

turbopack/crates/turbopack-tests/tests/snapshot/css/embed-url/output/4e721_crates_turbopack-tests_tests_snapshot_css_embed-url_input_index_a007acd1.js

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

turbopack/crates/turbopack-tests/tests/snapshot/css/embed-url/output/4e721_crates_turbopack-tests_tests_snapshot_css_embed-url_input_index_effff57f.js

-6
This file was deleted.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

turbopack/crates/turbopack-tests/tests/snapshot/css/embed-url/output/turbopack_crates_turbopack-tests_tests_snapshot_css_embed-url_input_39fdb40e._.js.map

-5
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/turbopack_crates_turbopack-tests_tests_snapshot_css_embed-url_input_39fdb40e._.js", {
1+
(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/turbopack_crates_turbopack-tests_tests_snapshot_css_embed-url_input_e139c187._.js", {
22

33
"[project]/turbopack/crates/turbopack-tests/tests/snapshot/css/embed-url/input/style.module.css [test] (css module, async loader)": ((__turbopack_context__) => {
44

0 commit comments

Comments
 (0)