Skip to content

Commit

Permalink
fix dynamic paths (vercel#2884)
Browse files Browse the repository at this point in the history
  • Loading branch information
ForsakenHarmony authored Dec 2, 2022
1 parent eead906 commit 4a3cb94
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 16 deletions.
3 changes: 3 additions & 0 deletions crates/next-core/js/src/entry/server-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ async function runOperation(
},
};

if ("getStaticPaths" in otherExports) {
renderOpts.getStaticPaths = otherExports.getStaticPaths;
}
if ("getStaticProps" in otherExports) {
renderOpts.getStaticProps = otherExports.getStaticProps;
}
Expand Down
18 changes: 11 additions & 7 deletions crates/next-core/src/app_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
io::Write,
};

use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, Result};
use turbo_tasks::{
primitives::{StringVc, StringsVc},
TryJoinIterExt, Value, ValueToString,
Expand Down Expand Up @@ -66,7 +66,7 @@ use crate::{
get_server_environment, get_server_module_options_context,
get_server_resolve_options_context, ServerContextType,
},
util::regular_expression_for_path,
util::{pathname_for_path, regular_expression_for_path},
};

#[turbo_tasks::function]
Expand Down Expand Up @@ -315,12 +315,12 @@ async fn create_app_source_for_directory(

let layout = files.get("layout");

// If a page exists but no layout exists, create a basic root layout
// in `app/layout.js` or `app/layout.tsx`.
//
// TODO: Use let Some(page_file) = page in expression below when
// https://rust-lang.github.io/rfcs/2497-if-let-chains.html lands
if page.is_some() && layout.is_none() && target == server_root {
// If a page exists but no layout exists, create a basic root layout
// in `app/layout.js` or `app/layout.tsx`.
let page_file = page.context("page must not be none")?;
if let (Some(page_file), None, true) = (page, layout, target == server_root) {
// Use the extension to determine if the page file is TypeScript.
// TODO: Use the presence of a tsconfig.json instead, like Next.js
// stable does.
Expand Down Expand Up @@ -358,10 +358,14 @@ async fn create_app_source_for_directory(
list.push(LayoutSegment { files, target }.cell());
layouts = LayoutSegmentsVc::cell(list);
if let Some(page_path) = page {
let pathname = pathname_for_path(server_root, target, false);
let path_regex = regular_expression_for_path(server_root, target, false);

sources.push(create_node_rendered_source(
specificity,
server_root,
regular_expression_for_path(server_root, target, false),
pathname,
path_regex,
AppRenderer {
context_ssr,
context,
Expand Down
10 changes: 7 additions & 3 deletions crates/next-core/src/server_rendered_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use crate::{
get_server_environment, get_server_module_options_context,
get_server_resolve_options_context, ServerContextType,
},
util::regular_expression_for_path,
util::{pathname_for_path, regular_expression_for_path},
};

/// Create a content source serving the `pages` or `src/pages` directory as
Expand Down Expand Up @@ -166,11 +166,14 @@ async fn create_server_rendered_source_for_file(
)
.build();

let pathname = pathname_for_path(server_root, server_path, true);
let path_regex = regular_expression_for_path(server_root, server_path, true);

Ok(if *is_api_path.await? {
create_node_api_source(
specificity,
server_root,
regular_expression_for_path(server_root, server_path, true),
path_regex,
SsrEntry {
context,
entry_asset,
Expand All @@ -186,7 +189,8 @@ async fn create_server_rendered_source_for_file(
create_node_rendered_source(
specificity,
server_root,
regular_expression_for_path(server_root, server_path, true),
pathname,
path_regex,
SsrEntry {
context,
entry_asset,
Expand Down
23 changes: 18 additions & 5 deletions crates/next-core/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
use anyhow::{anyhow, bail, Result};
use turbo_tasks::ValueToString;
use turbo_tasks::{primitives::StringVc, ValueToString};
use turbo_tasks_fs::FileSystemPathVc;
use turbopack_node::path_regex::{PathRegexBuilder, PathRegexVc};

/// Converts a filename within the server root to a regular expression with
/// named capture groups for every dynamic segment.
/// Converts a filename within the server root into a next pathname.
#[turbo_tasks::function]
pub async fn regular_expression_for_path(
pub async fn pathname_for_path(
server_root: FileSystemPathVc,
server_path: FileSystemPathVc,
has_extension: bool,
) -> Result<PathRegexVc> {
) -> Result<StringVc> {
let server_path_value = &*server_path.await?;
let path = if let Some(path) = server_root.await?.get_path_to(server_path_value) {
path
Expand All @@ -33,6 +32,20 @@ pub async fn regular_expression_for_path(
} else {
path.strip_suffix("/index").unwrap_or(path)
};

Ok(StringVc::cell(path.to_string()))
}

/// Converts a filename within the server root into a regular expression with
/// named capture groups for every dynamic segment.
#[turbo_tasks::function]
pub async fn regular_expression_for_path(
server_root: FileSystemPathVc,
server_path: FileSystemPathVc,
has_extension: bool,
) -> Result<PathRegexVc> {
let path = pathname_for_path(server_root, server_path, has_extension).await?;

let mut path_regex = PathRegexBuilder::new();
for segment in path.split('/') {
if let Some(segment) = segment.strip_prefix('[') {
Expand Down
5 changes: 4 additions & 1 deletion crates/turbopack-node/src/node_rendered_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use crate::path_regex::PathRegexVc;
pub fn create_node_rendered_source(
specificity: SpecificityVc,
server_root: FileSystemPathVc,
pathname: StringVc,
path_regex: PathRegexVc,
entry: NodeEntryVc,
runtime_entries: EcmascriptChunkPlaceablesVc,
Expand All @@ -46,6 +47,7 @@ pub fn create_node_rendered_source(
let source = NodeRenderContentSource {
specificity,
server_root,
pathname,
path_regex,
entry,
runtime_entries,
Expand All @@ -68,6 +70,7 @@ pub fn create_node_rendered_source(
struct NodeRenderContentSource {
specificity: SpecificityVc,
server_root: FileSystemPathVc,
pathname: StringVc,
path_regex: PathRegexVc,
entry: NodeEntryVc,
runtime_entries: EcmascriptChunkPlaceablesVc,
Expand Down Expand Up @@ -176,7 +179,7 @@ impl ContentSource for NodeRenderContentSource {
.headers
.clone()
.ok_or_else(|| anyhow!("headers needs to be provided"))?,
path: format!("/{path}"),
path: format!("/{}", this.pathname.await?),
}
.cell(),
);
Expand Down

0 comments on commit 4a3cb94

Please sign in to comment.