Skip to content

Commit

Permalink
Merge branch 'canary' into sebbie/10-15-next-upgrade_update_all_next.…
Browse files Browse the repository at this point in the history
…js_packages
  • Loading branch information
ijjk authored Oct 15, 2024
2 parents c858b13 + 51e1a24 commit 169bebd
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 121 deletions.
28 changes: 16 additions & 12 deletions crates/next-api/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,13 +815,12 @@ impl AppEndpoint {

let app_entry = self.app_endpoint_entry().await?;

let (process_client, process_ssr) = match this.ty {
AppEndpointType::Page { ty, .. } => (true, matches!(ty, AppPageEndpointType::Html)),
// NOTE(alexkirsz) For routes, technically, a lot of the following code is not needed,
// as we know we won't have any client references. However, for now, for simplicity's
// sake, we just do the same thing as for pages.
AppEndpointType::Route { .. } => (false, false),
AppEndpointType::Metadata { .. } => (false, false),
let (process_client_components, process_client_assets, process_ssr) = match this.ty {
AppEndpointType::Page { ty, .. } => {
(true, true, matches!(ty, AppPageEndpointType::Html))
}
AppEndpointType::Route { .. } => (true, false, false),
AppEndpointType::Metadata { .. } => (false, false, false),
};

let node_root = this.app_project.project().node_root();
Expand All @@ -843,7 +842,7 @@ impl AppEndpoint {
let client_chunking_context = this.app_project.project().client_chunking_context();

let (app_server_reference_modules, client_dynamic_imports, client_references) =
if process_client {
if process_client_components {
let client_shared_chunk_group = get_app_client_shared_chunk_group(
AssetIdent::from_path(this.app_project.project().project_path())
.with_modifier(client_shared_chunks()),
Expand Down Expand Up @@ -902,7 +901,7 @@ impl AppEndpoint {
NextRuntime::Edge => this
.app_project
.project()
.edge_chunking_context(process_client),
.edge_chunking_context(process_client_assets),
})
} else {
None
Expand Down Expand Up @@ -1138,7 +1137,7 @@ impl AppEndpoint {
let chunking_context = this
.app_project
.project()
.edge_chunking_context(process_client);
.edge_chunking_context(process_client_assets);
let mut evaluatable_assets = this
.app_project
.edge_rsc_runtime_entries()
Expand Down Expand Up @@ -1300,7 +1299,7 @@ impl AppEndpoint {
let chunking_context = this
.app_project
.project()
.server_chunking_context(process_client);
.server_chunking_context(process_client_assets);

if let Some(app_server_reference_modules) = app_server_reference_modules {
let (loader, manifest) = create_server_actions_manifest(
Expand Down Expand Up @@ -1354,7 +1353,12 @@ impl AppEndpoint {
.server_component_entries
.iter()
.copied()
.take(client_references.server_component_entries.len() - 1)
.take(
client_references
.server_component_entries
.len()
.saturating_sub(1),
)
{
let span = tracing::trace_span!(
"layout segment",
Expand Down
56 changes: 56 additions & 0 deletions crates/next-core/src/next_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ pub struct ExperimentalConfig {
after: Option<bool>,
amp: Option<serde_json::Value>,
app_document_preloading: Option<bool>,
cache_life: Option<FxIndexMap<String, CacheLifeProfile>>,
case_sensitive_routes: Option<bool>,
cpus: Option<f64>,
cra_compat: Option<bool>,
Expand Down Expand Up @@ -581,6 +582,61 @@ pub struct ExperimentalConfig {
worker_threads: Option<bool>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
#[serde(rename_all = "camelCase")]
pub struct CacheLifeProfile {
#[serde(skip_serializing_if = "Option::is_none")]
pub stale: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub revalidate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expire: Option<u32>,
}

#[test]
fn test_cache_life_profiles() {
let json = serde_json::json!({
"cacheLife": {
"frequent": {
"stale": 19,
"revalidate": 100,
},
}
});

let config: ExperimentalConfig = serde_json::from_value(json).unwrap();
let mut expected_cache_life = FxIndexMap::default();

expected_cache_life.insert(
"frequent".to_string(),
CacheLifeProfile {
stale: Some(19),
revalidate: Some(100),
expire: None,
},
);

assert_eq!(config.cache_life, Some(expected_cache_life));
}

#[test]
fn test_cache_life_profiles_invalid() {
let json = serde_json::json!({
"cacheLife": {
"invalid": {
"stale": "invalid_value",
},
}
});

let result: Result<ExperimentalConfig, _> = serde_json::from_value(json);

assert!(
result.is_err(),
"Deserialization should fail due to invalid 'stale' value type"
);
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
#[serde(rename_all = "lowercase")]
pub enum ExperimentalPartialPrerenderingIncrementalValue {
Expand Down
7 changes: 7 additions & 0 deletions crates/next-core/src/next_server/transforms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ pub async fn get_next_server_transforms_rules(
ActionsTransform::Client,
mdx_rs,
));

is_app_dir = true;

false
Expand All @@ -105,7 +106,13 @@ pub async fn get_next_server_transforms_rules(
true
}
ServerContextType::AppRoute { .. } => {
rules.push(get_server_actions_transform_rule(
ActionsTransform::Server,
mdx_rs,
));

is_app_dir = true;

false
}
ServerContextType::Middleware { .. } | ServerContextType::Instrumentation { .. } => false,
Expand Down
32 changes: 31 additions & 1 deletion packages/next/src/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1031,9 +1031,39 @@ export const defaultConfig: NextConfig = {
cacheLife: {
default: {
stale: undefined, // defaults to staleTimes.static
revalidate: 900,
revalidate: 60 * 15, // 15 minutes
expire: INFINITE_CACHE,
},
seconds: {
stale: undefined, // defaults to staleTimes.dynamic
revalidate: 1, // 1 second
expire: 1, // 1 minute
},
minutes: {
stale: 60 * 5, // 5 minutes
revalidate: 60, // 1 minute
expire: 60 * 60, // 1 hour
},
hours: {
stale: 60 * 5, // 5 minutes
revalidate: 60 * 60, // 1 hour
expire: 60 * 60 * 24, // 1 day
},
days: {
stale: 60 * 5, // 5 minutes
revalidate: 60 * 60 * 24, // 1 day
expire: 60 * 60 * 24 * 7, // 1 week
},
weeks: {
stale: 60 * 5, // 5 minutes
revalidate: 60 * 60 * 24 * 7, // 1 week
expire: 60 * 60 * 24 * 30, // 1 month
},
max: {
stale: 60 * 5, // 5 minutes
revalidate: 60 * 60 * 24 * 30, // 1 month
expire: INFINITE_CACHE, // Unbounded.
},
},
multiZoneDraftMode: false,
appNavFailHandling: Boolean(process.env.NEXT_PRIVATE_FLYING_SHUTTLE),
Expand Down
12 changes: 12 additions & 0 deletions packages/next/src/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,18 @@ function assignDefaults(
result.expireTime ?? defaultDefault.expire
}
}
// This is the most dynamic cache life profile.
const secondsCacheLifeProfile = result.experimental.cacheLife['seconds']
if (
secondsCacheLifeProfile &&
secondsCacheLifeProfile.stale === undefined
) {
// We default this to whatever stale time you had configured for dynamic content.
// Since this is basically a dynamic cache life profile.
const dynamicStaleTime = result.experimental.staleTimes?.dynamic
secondsCacheLifeProfile.stale =
dynamicStaleTime ?? defaultConfig.experimental?.staleTimes?.dynamic
}
}

const userProvidedModularizeImports = result.modularizeImports
Expand Down
11 changes: 10 additions & 1 deletion packages/next/src/server/use-cache/cache-life.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,16 @@ export type CacheLife = {
// The default revalidates relatively frequently but doesn't expire to ensure it's always
// able to serve fast results but by default doesn't hang.

type CacheLifeProfiles = string // This gets overridden by the next-types-plugin
// This gets overridden by the next-types-plugin
type CacheLifeProfiles =
| 'default'
| 'seconds'
| 'minutes'
| 'hours'
| 'days'
| 'weeks'
| 'max'
| string

function validateCacheLife(profile: CacheLife) {
if (profile.stale !== undefined) {
Expand Down
56 changes: 31 additions & 25 deletions test/development/acceptance-app/ReactRefreshLogBox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1209,35 +1209,40 @@ export default function Home() {
await cleanup()
})

test('Should collapse bundler internal stack frames', async () => {
const { session, browser, cleanup } = await sandbox(
next,
new Map([
[
'app/utils.ts',
`throw new Error('utils error')
// TODO: Fails with Webpack since
// https://github.com/vercel/next.js/pull/71312, not reproducible locally,
// investigate why.
;(isTurbopack ? test : test.skip)(
'Should collapse bundler internal stack frames',
async () => {
const { session, browser, cleanup } = await sandbox(
next,
new Map([
[
'app/utils.ts',
`throw new Error('utils error')
export function foo(){}`,
],
[
'app/page.js',
`"use client";
],
[
'app/page.js',
`"use client";
import { foo } from "./utils";
export default function Home() {
foo();
return "hello";
}`,
],
])
)
],
])
)

await session.assertHasRedbox()
await session.assertHasRedbox()

let stack = next.normalizeTestDirContent(
await getRedboxCallStackCollapsed(browser)
)
if (isTurbopack) {
expect(stack).toMatchInlineSnapshot(`
let stack = next.normalizeTestDirContent(
await getRedboxCallStackCollapsed(browser)
)
if (isTurbopack) {
expect(stack).toMatchInlineSnapshot(`
"app/utils.ts (1:7) @ [project]/app/utils.ts [app-client] (ecmascript)
---
Next.js
Expand All @@ -1249,8 +1254,8 @@ export default function Home() {
---
React"
`)
} else {
expect(stack).toMatchInlineSnapshot(`
} else {
expect(stack).toMatchInlineSnapshot(`
"app/utils.ts (1:7) @ eval
---
(app-pages-browser)/./app/utils.ts
Expand All @@ -1268,8 +1273,9 @@ export default function Home() {
---
React"
`)
}
}

await cleanup()
})
await cleanup()
}
)
})
Loading

0 comments on commit 169bebd

Please sign in to comment.