next_core/next_server_component/
server_component_transition.rs

1use anyhow::{Result, bail};
2use turbo_rcstr::RcStr;
3use turbo_tasks::Vc;
4use turbopack::{ModuleAssetContext, transition::Transition};
5use turbopack_core::module::Module;
6use turbopack_ecmascript::chunk::EcmascriptChunkPlaceable;
7
8use super::server_component_module::NextServerComponentModule;
9
10/// This transition wraps a module into a marker
11/// [`Vc<NextServerComponentModule>`].
12///
13/// When walking the module graph to build the client reference manifest, this
14/// is used to determine under which server component CSS client references are
15/// required. Ultimately, this tells Next.js what CSS to inject into the page.
16#[turbo_tasks::value(shared)]
17pub struct NextServerComponentTransition {}
18
19#[turbo_tasks::value_impl]
20impl NextServerComponentTransition {
21    /// Creates a new [`Vc<NextServerComponentTransition>`].
22    #[turbo_tasks::function]
23    pub fn new() -> Vc<Self> {
24        NextServerComponentTransition {}.cell()
25    }
26}
27
28#[turbo_tasks::value_impl]
29impl Transition for NextServerComponentTransition {
30    #[turbo_tasks::function]
31    fn process_layer(self: Vc<Self>, layer: Vc<RcStr>) -> Vc<RcStr> {
32        layer
33    }
34
35    #[turbo_tasks::function]
36    async fn process_module(
37        self: Vc<Self>,
38        module: Vc<Box<dyn Module>>,
39        _context: Vc<ModuleAssetContext>,
40    ) -> Result<Vc<Box<dyn Module>>> {
41        let Some(module) =
42            Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(module).await?
43        else {
44            bail!("not an ecmascript module");
45        };
46
47        Ok(Vc::upcast(NextServerComponentModule::new(module)))
48    }
49}