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

Turbopack: refactor CssEmbed to avoid creating a chunk item #77303

Merged
merged 6 commits into from
Mar 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
363 changes: 210 additions & 153 deletions test/integration/css/test/basic-global-support.test.js

Large diffs are not rendered by default.

30 changes: 22 additions & 8 deletions turbopack/crates/turbopack-css/src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use turbopack_core::{
ident::AssetIdent,
module::Module,
module_graph::ModuleGraph,
output::OutputAssets,
reference::{ModuleReference, ModuleReferences},
reference_type::ImportContext,
resolve::origin::ResolveOrigin,
Expand All @@ -22,7 +23,9 @@ use crate::{
finalize_css, parse_css, process_css_with_placeholder, CssWithPlaceholderResult,
FinalCssResult, ParseCss, ParseCssResult, ProcessCss,
},
references::{compose::CssModuleComposeReference, import::ImportAssetReference},
references::{
compose::CssModuleComposeReference, import::ImportAssetReference, url::ReferencedAsset,
},
CssModuleAssetType,
};

Expand Down Expand Up @@ -95,13 +98,12 @@ impl ProcessCss for CssModuleAsset {
#[turbo_tasks::function]
fn finalize_css(
self: Vc<Self>,
module_graph: Vc<ModuleGraph>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
minify_type: MinifyType,
) -> Vc<FinalCssResult> {
let process_result = self.get_css_with_placeholder();

finalize_css(process_result, module_graph, chunking_context, minify_type)
finalize_css(process_result, chunking_context, minify_type)
}
}

Expand Down Expand Up @@ -201,6 +203,22 @@ impl ChunkItem for CssModuleChunkItem {
fn module(&self) -> Vc<Box<dyn Module>> {
Vc::upcast(*self.module)
}

#[turbo_tasks::function]
async fn references(&self) -> Result<Vc<OutputAssets>> {
let mut references = Vec::new();
if let ParseCssResult::Ok { url_references, .. } = &*self.module.parse_css().await? {
for (_, reference) in url_references.await? {
if let ReferencedAsset::Some(asset) = *reference
.get_referenced_asset(*self.chunking_context)
.await?
{
references.push(asset);
}
}
}
Ok(Vc::cell(references))
}
}

#[turbo_tasks::value_impl]
Expand Down Expand Up @@ -280,11 +298,7 @@ impl CssChunkItem for CssModuleChunkItem {

let result = self
.module
.finalize_css(
*self.module_graph,
*chunking_context,
self.module.await?.minify_type,
)
.finalize_css(*chunking_context, self.module.await?.minify_type)
.await?;

if let FinalCssResult::Ok {
Expand Down
9 changes: 6 additions & 3 deletions turbopack/crates/turbopack-css/src/embed.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use turbo_tasks::Vc;
use turbopack_core::{chunk::ChunkItem, output::OutputAsset};
use turbopack_core::{asset::Asset, chunk::ChunkingContext, module::Module, output::OutputAsset};

#[turbo_tasks::value_trait]
pub trait CssEmbed: ChunkItem {
fn embedded_asset(self: Vc<Self>) -> Vc<Box<dyn OutputAsset>>;
pub trait CssEmbed: Module + Asset {
fn embedded_asset(
self: Vc<Self>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
) -> Vc<Box<dyn OutputAsset>>;
}
6 changes: 1 addition & 5 deletions turbopack/crates/turbopack-css/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use turbopack_core::{
Issue, IssueExt, IssueSource, IssueStage, OptionIssueSource, OptionStyledString,
StyledString,
},
module_graph::ModuleGraph,
reference::ModuleReferences,
reference_type::ImportContext,
resolve::origin::ResolveOrigin,
Expand Down Expand Up @@ -220,7 +219,6 @@ pub async fn process_css_with_placeholder(
#[turbo_tasks::function]
pub async fn finalize_css(
result: Vc<CssWithPlaceholderResult>,
module_graph: Vc<ModuleGraph>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
minify_type: MinifyType,
) -> Result<Vc<FinalCssResult>> {
Expand All @@ -247,8 +245,7 @@ pub async fn finalize_css(
let mut url_map = FxHashMap::default();

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

async fn finalize_css(
self: Vc<Self>,
module_graph: Vc<ModuleGraph>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
minify_type: MinifyType,
) -> Result<Vc<FinalCssResult>>;
Expand Down
40 changes: 14 additions & 26 deletions turbopack/crates/turbopack-css/src/references/url.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
use std::convert::Infallible;

use anyhow::{bail, Result};
use anyhow::Result;
use lightningcss::{
values::url::Url,
visit_types,
visitor::{Visit, Visitor},
};
use rustc_hash::FxHashMap;
use turbo_rcstr::RcStr;
use turbo_tasks::{debug::ValueDebug, ResolvedVc, Value, ValueToString, Vc};
use turbo_tasks::{ResolvedVc, Value, ValueToString, Vc};
use turbopack_core::{
chunk::{ChunkableModule, ChunkableModuleReference, ChunkingContext},
chunk::{ChunkableModuleReference, ChunkingContext},
ident::AssetIdent,
issue::IssueSource,
module_graph::ModuleGraph,
output::OutputAsset,
reference::ModuleReference,
reference_type::{ReferenceType, UrlReferenceSubType},
Expand Down Expand Up @@ -52,28 +51,21 @@ impl UrlAssetReference {
}

#[turbo_tasks::function]
async fn get_referenced_asset(
pub async fn get_referenced_asset(
self: Vc<Self>,
module_graph: Vc<ModuleGraph>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
) -> Result<Vc<ReferencedAsset>> {
if let Some(module) = *self.resolve_reference().first_module().await? {
if let Some(chunkable) = ResolvedVc::try_downcast::<Box<dyn ChunkableModule>>(module) {
let chunk_item = chunkable.as_chunk_item(module_graph, chunking_context);
if let Some(embeddable) =
Vc::try_resolve_downcast::<Box<dyn CssEmbed>>(chunk_item).await?
{
return Ok(ReferencedAsset::Some(
embeddable.embedded_asset().to_resolved().await?,
)
.into());
}
if let Some(embeddable) = Vc::try_resolve_downcast::<Box<dyn CssEmbed>>(*module).await?
{
return Ok(ReferencedAsset::Some(
embeddable
.embedded_asset(chunking_context)
.to_resolved()
.await?,
)
.into());
}
bail!(
"A module referenced by a url() reference must be chunkable and the chunk item \
must be css embeddable\nreferenced module: {:?}",
module.dbg_depth(1).await?
)
}
Ok(ReferencedAsset::cell(ReferencedAsset::None))
}
Expand Down Expand Up @@ -109,7 +101,6 @@ impl ValueToString for UrlAssetReference {
#[turbo_tasks::function]
pub async fn resolve_url_reference(
url: Vc<UrlAssetReference>,
module_graph: Vc<ModuleGraph>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
) -> Result<Vc<Option<RcStr>>> {
let this = url.await?;
Expand All @@ -121,10 +112,7 @@ pub async fn resolve_url_reference(
);
let context_path = chunk_path.parent().await?;

if let ReferencedAsset::Some(asset) = &*url
.get_referenced_asset(module_graph, chunking_context)
.await?
{
if let ReferencedAsset::Some(asset) = &*url.get_referenced_asset(chunking_context).await? {
// TODO(WEB-662) This is not the correct way to get the path of the asset.
// `asset` is on module-level, but we need the output-level asset instead.
let path = asset.path().await?;
Expand Down
116 changes: 9 additions & 107 deletions turbopack/crates/turbopack-static/src/css.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
use anyhow::Result;
use turbo_rcstr::RcStr;
use turbo_tasks::{ResolvedVc, Vc};
use turbopack_core::{
asset::{Asset, AssetContent},
chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkingContext},
chunk::ChunkingContext,
ident::AssetIdent,
module::Module,
module_graph::ModuleGraph,
output::{OutputAsset, OutputAssets},
output::OutputAsset,
source::Source,
};
use turbopack_css::{
chunk::{CssChunkItem, CssChunkItemContent, CssChunkType},
embed::CssEmbed,
};
use turbopack_ecmascript::{
chunk::{EcmascriptChunkPlaceable, EcmascriptExports},
utils::StringifyJs,
};
use turbopack_css::embed::CssEmbed;

use crate::output_asset::StaticOutputAsset;

Expand Down Expand Up @@ -65,102 +56,13 @@ impl Asset for StaticUrlCssModule {
}

#[turbo_tasks::value_impl]
impl ChunkableModule for StaticUrlCssModule {
#[turbo_tasks::function]
async fn as_chunk_item(
self: ResolvedVc<Self>,
_module_graph: Vc<ModuleGraph>,
chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
) -> Result<Vc<Box<dyn turbopack_core::chunk::ChunkItem>>> {
Ok(Vc::upcast(StaticUrlCssChunkItem::cell(
StaticUrlCssChunkItem {
module: self,
chunking_context,
static_asset: self
.static_output_asset(*ResolvedVc::upcast(chunking_context))
.to_resolved()
.await?,
},
)))
}
}

#[turbo_tasks::value_impl]
impl EcmascriptChunkPlaceable for StaticUrlCssModule {
#[turbo_tasks::function]
fn get_exports(&self) -> Vc<EcmascriptExports> {
EcmascriptExports::Value.into()
}
}

#[turbo_tasks::value]
struct StaticUrlCssChunkItem {
module: ResolvedVc<StaticUrlCssModule>,
chunking_context: ResolvedVc<Box<dyn ChunkingContext>>,
static_asset: ResolvedVc<StaticOutputAsset>,
}

#[turbo_tasks::value_impl]
impl ChunkItem for StaticUrlCssChunkItem {
#[turbo_tasks::function]
fn asset_ident(&self) -> Vc<AssetIdent> {
self.module.ident()
}

#[turbo_tasks::function]
fn references(&self) -> Vc<OutputAssets> {
Vc::cell(vec![ResolvedVc::upcast(self.static_asset)])
}

#[turbo_tasks::function]
fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
*ResolvedVc::upcast(self.chunking_context)
}

#[turbo_tasks::function]
async fn ty(&self) -> Result<Vc<Box<dyn ChunkType>>> {
Ok(Vc::upcast(Vc::<CssChunkType>::default().resolve().await?))
}

#[turbo_tasks::function]
fn module(&self) -> Vc<Box<dyn Module>> {
*ResolvedVc::upcast(self.module)
}
}

#[turbo_tasks::value_impl]
impl CssChunkItem for StaticUrlCssChunkItem {
#[turbo_tasks::function]
fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> {
*self.chunking_context
}

#[turbo_tasks::function]
async fn content(&self) -> Result<Vc<CssChunkItemContent>> {
Ok(CssChunkItemContent {
import_context: None,
imports: Vec::new(),
source_map: None,
inner_code: format!(
"/* embedded static asset {path} */",
path = StringifyJs(
&self
.chunking_context
.asset_url(self.static_asset.path())
.await?
)
)
.into(),
}
.into())
}
}

#[turbo_tasks::value_impl]
impl CssEmbed for StaticUrlCssChunkItem {
impl CssEmbed for StaticUrlCssModule {
#[turbo_tasks::function]
fn embedded_asset(&self) -> Vc<Box<dyn OutputAsset>> {
*ResolvedVc::upcast(self.static_asset)
fn embedded_asset(
self: Vc<Self>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
) -> Vc<Box<dyn OutputAsset>> {
Vc::upcast(self.static_output_asset(chunking_context))
}
}

Expand Down

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/turbopack_crates_turbopack-tests_tests_snapshot_css_embed-url_input_39fdb40e._.js", {
(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/turbopack_crates_turbopack-tests_tests_snapshot_css_embed-url_input_e139c187._.js", {

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

Expand Down
Loading