Repository: vercel/next.js
Pull request: [turbopack] Conditionally create pages router data endpoints.

Pages router data endpoints are only needed or used in `dev` but we would unconditionally create them even in `build` scenarios`.

This clarifies the API and modifies `endpoint` collection to also collect these when they exist.  This will unblock enabling the `whole_app_module_graph`

Closes PACK-5578

Changed files:
filename: crates/next-api/src/operation.rs
patch: @@ -166,7 +166,7 @@ async fn pick_endpoint(
         }
         EndpointSelector::RoutePageData(name) => {
             if let Some(Route::Page { data_endpoint, .. }) = endpoints.routes.get(&name) {
-                Some(*data_endpoint)
+                *data_endpoint
             } else {
                 None
             }

filename: crates/next-api/src/pages.rs
patch: @@ -199,18 +199,23 @@ impl PagesProject {
                         .to_resolved()
                         .await?,
                     ),
-                    data_endpoint: ResolvedVc::upcast(
-                        PageEndpoint::new(
-                            PageEndpointType::Data,
-                            self,
-                            pathname,
-                            original_name,
-                            page,
-                            pages_structure,
-                        )
-                        .to_resolved()
-                        .await?,
-                    ),
+                    // The data endpoint is only needed in development mode to support HMR
+                    data_endpoint: if self.project().next_mode().await?.is_development() {
+                        Some(ResolvedVc::upcast(
+                            PageEndpoint::new(
+                                PageEndpointType::Data,
+                                self,
+                                pathname,
+                                original_name,
+                                page,
+                                pages_structure,
+                            )
+                            .to_resolved()
+                            .await?,
+                        ))
+                    } else {
+                        None
+                    },
                 })
             })
         };
@@ -653,7 +658,7 @@ impl PageEndpoint {
             if self.ty == PageEndpointType::Data {
                 rcstr!("?server-data")
             } else {
-                RcStr::default()
+                rcstr!("")
             },
         )))
     }
@@ -719,8 +724,8 @@ impl PageEndpoint {
         let this = self.await?;
         let project = this.pages_project.project();
 
-        let should_trace = project.next_mode().await?.is_production();
         if *project.per_page_module_graph().await? {
+            let should_trace = project.next_mode().await?.is_production();
             let ssr_chunk_module = self.internal_ssr_chunk_module().await?;
             // Implements layout segment optimization to compute a graph "chain" for document, app,
             // page

filename: crates/next-api/src/project.rs
patch: @@ -863,7 +863,7 @@ impl Project {
             match route {
                 Route::Page {
                     html_endpoint,
-                    data_endpoint: _,
+                    data_endpoint,
                 } => {
                     if !app_dir_only {
                         endpoints.push(*html_endpoint);
@@ -873,6 +873,10 @@ impl Project {
                             endpoints.push(entrypoints.pages_document_endpoint);
                             is_pages_entries_added = true;
                         }
+                        // This only exists in development mode for HMR
+                        if let Some(data_endpoint) = data_endpoint {
+                            endpoints.push(*data_endpoint);
+                        }
                     }
                 }
                 Route::PageApi { endpoint } => {

filename: crates/next-api/src/route.rs
patch: @@ -34,7 +34,7 @@ pub struct AppPageRoute {
 pub enum Route {
     Page {
         html_endpoint: ResolvedVc<Box<dyn Endpoint>>,
-        data_endpoint: ResolvedVc<Box<dyn Endpoint>>,
+        data_endpoint: Option<ResolvedVc<Box<dyn Endpoint>>>,
     },
     PageApi {
         endpoint: ResolvedVc<Box<dyn Endpoint>>,