diff --git a/packages/next-swc/crates/next-api/src/project.rs b/packages/next-swc/crates/next-api/src/project.rs index fb0b1f083a3c6..6823e4a2e74f3 100644 --- a/packages/next-swc/crates/next-api/src/project.rs +++ b/packages/next-swc/crates/next-api/src/project.rs @@ -5,7 +5,8 @@ use indexmap::{map::Entry, IndexMap}; use next_core::{ all_assets_from_entries, app_structure::find_app_dir, - get_edge_chunking_context, get_edge_compile_time_info, get_edge_resolve_options_context, + emit_assets, get_edge_chunking_context, get_edge_compile_time_info, + get_edge_resolve_options_context, instrumentation::instrumentation_files, middleware::middleware_files, mode::NextMode, @@ -797,14 +798,17 @@ impl Project { let client_relative_path = self.client_relative_path(); let node_root = self.node_root(); - let completion = self.await?.versioned_content_map.insert_output_assets( - all_output_assets, - node_root, + self.await? + .versioned_content_map + .insert_output_assets(all_output_assets, client_relative_path, node_root) + .await?; + + Ok(emit_assets( + *all_output_assets.await?, + self.node_root(), client_relative_path, node_root, - ); - - Ok(completion) + )) } .instrument(span) .await diff --git a/packages/next-swc/crates/next-api/src/versioned_content_map.rs b/packages/next-swc/crates/next-api/src/versioned_content_map.rs index d659ee94ec863..b566534a00715 100644 --- a/packages/next-swc/crates/next-api/src/versioned_content_map.rs +++ b/packages/next-swc/crates/next-api/src/versioned_content_map.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use anyhow::{bail, Result}; -use next_core::emit_assets; +use next_core::emit_client_assets; use serde::{Deserialize, Serialize}; use turbo_tasks::{ debug::ValueDebugFormat, trace::TraceRawVcs, Completion, State, TryFlatJoinIterExt, @@ -64,18 +64,13 @@ impl VersionedContentMap { pub async fn insert_output_assets( self: Vc, assets_operation: Vc, - node_root: Vc, client_relative_path: Vc, client_output_path: Vc, - ) -> Result> { + ) -> Result<()> { let assets_operation = *assets_operation.await?; // Make sure all written client assets are up-to-date - let emit_operation = emit_assets( - assets_operation.resolve().await?, - node_root, - client_relative_path, - client_output_path, - ); + let emit_operation = + emit_client_assets(assets_operation, client_relative_path, client_output_path); let assets = assets_operation.await?; let entries: Vec<_> = assets .iter() @@ -94,7 +89,7 @@ impl VersionedContentMap { map.extend(entries); true }); - Ok(emit_operation) + Ok(()) } #[turbo_tasks::function] diff --git a/packages/next-swc/crates/next-core/src/emit.rs b/packages/next-swc/crates/next-core/src/emit.rs index 9130ed618931e..143789bbdd545 100644 --- a/packages/next-swc/crates/next-core/src/emit.rs +++ b/packages/next-swc/crates/next-core/src/emit.rs @@ -1,8 +1,7 @@ use anyhow::Result; -use tracing::Instrument; use turbo_tasks::{ graph::{AdjacencyMap, GraphTraversal}, - Completion, Completions, TryFlatJoinIterExt, ValueToString, Vc, + Completion, Completions, TryFlatJoinIterExt, Vc, }; use turbo_tasks_fs::{rebase, FileSystemPath}; use turbopack_binding::turbopack::core::{ @@ -48,24 +47,69 @@ pub async fn emit_assets( .iter() .copied() .map(|asset| async move { - let asset = asset.resolve().await?; - let path = asset.ident().path(); - let span = tracing::info_span!("emit asset", name = &*path.to_string().await?); - async move { - let path = path.await?; - Ok(if path.is_inside_ref(&*node_root.await?) { - Some(emit(asset)) - } else if path.is_inside_ref(&*client_relative_path.await?) { - // Client assets are emitted to the client output path, which is prefixed - // with _next. We need to rebase them to remove that - // prefix. - Some(emit_rebase(asset, client_relative_path, client_output_path)) - } else { - None - }) + if asset + .ident() + .path() + .await? + .is_inside_ref(&*node_root.await?) + { + return Ok(Some(emit(asset))); + } else if asset + .ident() + .path() + .await? + .is_inside_ref(&*client_relative_path.await?) + { + // Client assets are emitted to the client output path, which is prefixed with + // _next. We need to rebase them to remove that prefix. + return Ok(Some(emit_rebase( + asset, + client_relative_path, + client_output_path, + ))); } - .instrument(span) - .await + + Ok(None) + }) + .try_flat_join() + .await?, + ) + .completed()) +} + +/// Emits all assets transitively reachable from the given chunks, that are +/// inside the client root. +/// +/// Assets inside the given client root are rebased to the given client output +/// path. +#[turbo_tasks::function] +pub async fn emit_client_assets( + assets: Vc, + client_relative_path: Vc, + client_output_path: Vc, +) -> Result> { + Ok(Vc::::cell( + assets + .await? + .iter() + .copied() + .map(|asset| async move { + if asset + .ident() + .path() + .await? + .is_inside_ref(&*client_relative_path.await?) + { + // Client assets are emitted to the client output path, which is prefixed with + // _next. We need to rebase them to remove that prefix. + return Ok(Some(emit_rebase( + asset, + client_relative_path, + client_output_path, + ))); + } + + Ok(None) }) .try_flat_join() .await?, @@ -79,14 +123,14 @@ fn emit(asset: Vc>) -> Vc { } #[turbo_tasks::function] -async fn emit_rebase( +fn emit_rebase( asset: Vc>, from: Vc, to: Vc, -) -> Result> { - let path = rebase(asset.ident().path(), from, to); - let content = asset.content(); - Ok(content.resolve().await?.write(path.resolve().await?)) +) -> Vc { + asset + .content() + .write(rebase(asset.ident().path(), from, to)) } /// Walks the asset graph from multiple assets and collect all referenced diff --git a/packages/next-swc/crates/next-core/src/lib.rs b/packages/next-swc/crates/next-core/src/lib.rs index 7c685786ba8ed..2cbd79a79bad2 100644 --- a/packages/next-swc/crates/next-core/src/lib.rs +++ b/packages/next-swc/crates/next-core/src/lib.rs @@ -44,7 +44,7 @@ pub mod util; pub use app_segment_config::{ parse_segment_config_from_loader_tree, parse_segment_config_from_source, }; -pub use emit::{all_assets_from_entries, emit_all_assets, emit_assets}; +pub use emit::{all_assets_from_entries, emit_all_assets, emit_assets, emit_client_assets}; pub use next_edge::context::{ get_edge_chunking_context, get_edge_compile_time_info, get_edge_resolve_options_context, };