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

Add app, error, and document entrypoints #53013

Merged
merged 3 commits into from Jul 24, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions packages/next-swc/crates/napi/src/next_api/project.rs
Expand Up @@ -207,6 +207,9 @@ impl NapiMiddleware {
struct NapiEntrypoints {
pub routes: Vec<NapiRoute>,
pub middleware: Option<NapiMiddleware>,
pub pages_document_endpoint: External<ExternalEndpoint>,
pub pages_app_endpoint: External<ExternalEndpoint>,
pub pages_error_endpoint: External<ExternalEndpoint>,
pub issues: Vec<NapiIssue>,
pub diagnostics: Vec<NapiDiagnostic>,
}
Expand Down Expand Up @@ -245,6 +248,18 @@ pub fn project_entrypoints_subscribe(
.as_ref()
.map(|m| NapiMiddleware::from_middleware(m, &turbo_tasks))
.transpose()?,
pages_document_endpoint: External::new(ExternalEndpoint(VcArc::new(
turbo_tasks.clone(),
entrypoints.pages_document_endpoint,
))),
pages_app_endpoint: External::new(ExternalEndpoint(VcArc::new(
turbo_tasks.clone(),
entrypoints.pages_app_endpoint,
))),
pages_error_endpoint: External::new(ExternalEndpoint(VcArc::new(
turbo_tasks.clone(),
entrypoints.pages_error_endpoint,
))),
issues: issues
.iter()
.map(|issue| NapiIssue::from(&**issue))
Expand Down
9 changes: 8 additions & 1 deletion packages/next-swc/crates/next-api/src/entrypoints.rs
@@ -1,9 +1,16 @@
use indexmap::IndexMap;
use turbo_tasks::Vc;

use crate::{project::Middleware, route::Route};
use crate::{
project::Middleware,
route::{Endpoint, Route},
};

#[turbo_tasks::value(shared)]
pub struct Entrypoints {
pub routes: IndexMap<String, Route>,
pub middleware: Option<Middleware>,
pub pages_document_endpoint: Vc<Box<dyn Endpoint>>,
pub pages_app_endpoint: Vc<Box<dyn Endpoint>>,
pub pages_error_endpoint: Vc<Box<dyn Endpoint>>,
}
125 changes: 94 additions & 31 deletions packages/next-swc/crates/next-api/src/pages.rs
Expand Up @@ -66,8 +66,33 @@ impl PagesProject {

#[turbo_tasks::function]
pub async fn routes(self: Vc<Self>) -> Result<Vc<Routes>> {
let PagesStructure { api, pages, .. } = &*self.pages_structure().await?;
let PagesStructure {
api,
pages,
app: _,
document: _,
error: _,
} = &*self.pages_structure().await?;
let mut routes = IndexMap::new();

async fn add_page_to_routes(
routes: &mut IndexMap<String, Route>,
page: Vc<PagesStructureItem>,
make_route: impl Fn(Vc<String>, Vc<String>, Vc<FileSystemPath>) -> Route,
) -> Result<()> {
let PagesStructureItem {
next_router_path,
project_path,
original_path,
} = *page.await?;
let pathname = format!("/{}", next_router_path.await?.path);
let pathname_vc = Vc::cell(pathname.clone());
let original_name = Vc::cell(format!("/{}", original_path.await?.path));
let route = make_route(pathname_vc, original_name, project_path);
routes.insert(pathname, route);
Ok(())
}

async fn add_dir_to_routes(
routes: &mut IndexMap<String, Route>,
dir: Vc<PagesDirectoryStructure>,
Expand All @@ -82,23 +107,15 @@ impl PagesProject {
project_path: _,
} = *dir.await?;
for &item in items.iter() {
let PagesStructureItem {
next_router_path,
project_path,
original_path,
} = *item.await?;
let pathname = format!("/{}", next_router_path.await?.path);
let pathname_vc = Vc::cell(pathname.clone());
let original_name = Vc::cell(format!("/{}", original_path.await?.path));
let route = make_route(pathname_vc, original_name, project_path);
routes.insert(pathname, route);
add_page_to_routes(routes, item, &make_route).await?;
}
for &child in children.iter() {
queue.push(child);
}
}
Ok(())
}

if let Some(api) = api {
add_dir_to_routes(&mut routes, *api, |pathname, original_name, path| {
Route::PageApi {
Expand All @@ -113,30 +130,74 @@ impl PagesProject {
})
.await?;
}
if let Some(page) = pages {
add_dir_to_routes(&mut routes, *page, |pathname, original_name, path| {
Route::Page {
html_endpoint: Vc::upcast(PageEndpoint::new(
PageEndpointType::Html,
self,
pathname,
original_name,
path,
)),
data_endpoint: Vc::upcast(PageEndpoint::new(
PageEndpointType::Data,
self,
pathname,
original_name,
path,
)),
}
})
.await?;

let make_page_route = |pathname, original_name, path| Route::Page {
html_endpoint: Vc::upcast(PageEndpoint::new(
PageEndpointType::Html,
self,
pathname,
original_name,
path,
)),
data_endpoint: Vc::upcast(PageEndpoint::new(
PageEndpointType::Data,
self,
pathname,
original_name,
path,
)),
};

if let Some(pages) = pages {
add_dir_to_routes(&mut routes, *pages, make_page_route).await?;
}

Ok(Vc::cell(routes))
}

#[turbo_tasks::function]
async fn to_endpoint(
self: Vc<Self>,
item: Vc<PagesStructureItem>,
ty: PageEndpointType,
) -> Result<Vc<Box<dyn Endpoint>>> {
let PagesStructureItem {
next_router_path,
project_path,
original_path,
} = *item.await?;
let pathname = format!("/{}", next_router_path.await?.path);
let pathname_vc = Vc::cell(pathname.clone());
let original_name = Vc::cell(format!("/{}", original_path.await?.path));
let path = project_path;
let endpoint = Vc::upcast(PageEndpoint::new(
ty,
self,
pathname_vc,
original_name,
path,
));
Ok(endpoint)
}

#[turbo_tasks::function]
pub async fn document_endpoint(self: Vc<Self>) -> Result<Vc<Box<dyn Endpoint>>> {
Ok(self.to_endpoint(
self.pages_structure().await?.document,
PageEndpointType::SsrOnly,
))
}

#[turbo_tasks::function]
pub async fn app_endpoint(self: Vc<Self>) -> Result<Vc<Box<dyn Endpoint>>> {
Ok(self.to_endpoint(self.pages_structure().await?.app, PageEndpointType::Html))
}

#[turbo_tasks::function]
pub async fn error_endpoint(self: Vc<Self>) -> Result<Vc<Box<dyn Endpoint>>> {
Ok(self.to_endpoint(self.pages_structure().await?.error, PageEndpointType::Html))
}

#[turbo_tasks::function]
fn project(&self) -> Vc<Project> {
self.project
Expand Down Expand Up @@ -407,6 +468,7 @@ enum PageEndpointType {
Api,
Html,
Data,
SsrOnly,
}

#[turbo_tasks::value_impl]
Expand Down Expand Up @@ -665,6 +727,7 @@ impl PageEndpoint {
}
PageEndpointType::Data => self.ssr_data_chunk(),
PageEndpointType::Api => self.api_chunk(),
PageEndpointType::SsrOnly => self.ssr_chunk(),
};

let page_output = match *ssr_chunk.await? {
Expand Down
3 changes: 3 additions & 0 deletions packages/next-swc/crates/next-api/src/project.rs
Expand Up @@ -373,6 +373,9 @@ impl Project {
Ok(Entrypoints {
routes,
middleware: None,
pages_document_endpoint: self.pages_project().document_endpoint(),
pages_app_endpoint: self.pages_project().app_endpoint(),
pages_error_endpoint: self.pages_project().error_endpoint(),
}
.cell())
}
Expand Down
13 changes: 13 additions & 0 deletions packages/next/src/build/swc/index.ts
Expand Up @@ -393,6 +393,9 @@ interface Middleware {
interface Entrypoints {
routes: Map<string, Route>
middleware?: Middleware
pagesDocumentEndpoint: Endpoint
pagesAppEndpoint: Endpoint
pagesErrorEndpoint: Endpoint
}

interface Project {
Expand Down Expand Up @@ -587,6 +590,9 @@ function bindingToApi(binding: any, _wasm: boolean) {
type NapiEntrypoints = {
routes: NapiRoute[]
middleware?: NapiMiddleware
pagesDocumentEndpoint: NapiEndpoint
pagesAppEndpoint: NapiEndpoint
pagesErrorEndpoint: NapiEndpoint
issues: Issue[]
diagnostics: Diagnostics[]
}
Expand Down Expand Up @@ -683,6 +689,13 @@ function bindingToApi(binding: any, _wasm: boolean) {
yield {
routes,
middleware,
pagesDocumentEndpoint: new EndpointImpl(
entrypoints.pagesDocumentEndpoint
),
pagesAppEndpoint: new EndpointImpl(entrypoints.pagesAppEndpoint),
pagesErrorEndpoint: new EndpointImpl(
entrypoints.pagesErrorEndpoint
),
issues: entrypoints.issues,
diagnostics: entrypoints.diagnostics,
}
Expand Down
20 changes: 13 additions & 7 deletions packages/next/src/cli/next-dev.ts
Expand Up @@ -240,20 +240,29 @@ const nextDev: CliCommand = async (argv) => {

// Just testing code here:

const project = await bindings.turbo.createProject({
const options = {
projectPath: dir,
rootPath: dir,
rootPath: args['--root'] ?? findRootDir(dir) ?? dir,
nextConfig: config,
env: {
NEXT_PUBLIC_ENV_VAR: 'world',
},
watch: true,
})
}
const project = await bindings.turbo.createProject(options)
const iter = project.entrypointsSubscribe()

try {
for await (const entrypoints of iter) {
Log.info(entrypoints)

Log.info(`writing _document to disk`)
Log.info(await entrypoints.pagesDocumentEndpoint.writeToDisk())
Log.info(`writing _app to disk`)
Log.info(await entrypoints.pagesAppEndpoint.writeToDisk())
Log.info(`writing _error to disk`)
Log.info(await entrypoints.pagesErrorEndpoint.writeToDisk())

for (const [pathname, route] of entrypoints.routes) {
switch (route.type) {
case 'page': {
Expand Down Expand Up @@ -287,13 +296,10 @@ const nextDev: CliCommand = async (argv) => {
}
Log.info('iteration done')
await project.update({
projectPath: dir,
rootPath: dir,
nextConfig: config,
...options,
env: {
NEXT_PUBLIC_ENV_VAR: 'hello',
},
watch: true,
})
}
} catch (e) {
Expand Down