diff --git a/Cargo.lock b/Cargo.lock index 4116cc31ed1e..6153b50b3f9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10370,10 +10370,12 @@ dependencies = [ name = "turbopack-ecmascript" version = "0.1.0" dependencies = [ + "allocator-api2", "anyhow", "async-trait", "auto-hash-map", "bincode 2.0.1", + "bumpalo", "bytes-str", "codspeed-criterion-compat", "dashmap 6.1.0", diff --git a/Cargo.toml b/Cargo.toml index 8ae5fc594d10..95f3ad9fae27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -240,6 +240,7 @@ chromiumoxide = { version = "0.5.4", features = [ # sync with chromiumoxide's tungstenite requirement. tungstenite = "0.20.1" +allocator-api2 = "0.2.21" # flate2_zlib requires zlib, use flate2_rust allsorts = { version = "0.14.0", default-features = false, features = [ "flate2_rust", @@ -248,6 +249,7 @@ anyhow = "1.0.100" async-trait = "0.1.64" bincode = { version = "2.0.1", features = ["serde"] } bitfield = "0.19.4" +bumpalo = { version = "3.19.0", features = ["boxed", "collections", "allocator-api2"] } byteorder = "1.5.0" bytes = "1.11.1" bytes-str = "0.2.7" diff --git a/crates/next-api/src/next_server_nft.rs b/crates/next-api/src/next_server_nft.rs index 8dd011243546..b46ccff0a26f 100644 --- a/crates/next-api/src/next_server_nft.rs +++ b/crates/next-api/src/next_server_nft.rs @@ -5,10 +5,7 @@ use bincode::{Decode, Encode}; use either::Either; use next_core::{get_next_package, next_server::get_tracing_compile_time_info}; use serde_json::json; -use turbo_tasks::{ - NonLocalValue, ResolvedVc, TaskInput, TryFlatJoinIterExt, TryJoinIterExt, Vc, - trace::TraceRawVcs, -}; +use turbo_tasks::{ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, Vc, trace::TraceRawVcs}; use turbo_tasks_fs::{ DirectoryContent, DirectoryEntry, File, FileContent, FileSystemPath, glob::Glob, }; @@ -26,9 +23,8 @@ use turbopack_resolve::ecmascript::cjs_resolve; use crate::{nft::traced_modules_for_entries, project::Project}; -#[derive( - PartialEq, Eq, TraceRawVcs, NonLocalValue, Debug, Clone, Hash, TaskInput, Encode, Decode, -)] +#[turbo_tasks::task_input] +#[derive(PartialEq, Eq, TraceRawVcs, Debug, Clone, Hash, Encode, Decode)] enum ServerNftType { Minimal, Full, diff --git a/crates/next-api/src/operation.rs b/crates/next-api/src/operation.rs index 2422329114d1..1f7cc4273a1e 100644 --- a/crates/next-api/src/operation.rs +++ b/crates/next-api/src/operation.rs @@ -2,7 +2,7 @@ use anyhow::Result; use bincode::{Decode, Encode}; use turbo_rcstr::RcStr; use turbo_tasks::{ - FxIndexMap, NonLocalValue, OperationValue, OperationVc, ResolvedVc, TaskInput, Vc, + FxIndexMap, NonLocalValue, OperationValue, OperationVc, ResolvedVc, Vc, debug::ValueDebugFormat, take_effects, trace::TraceRawVcs, }; use turbopack_core::issue::CollectibleIssuesExt; @@ -108,19 +108,9 @@ fn pick_route(entrypoints: OperationVc, key: RcStr, route: &Route) } } +#[turbo_tasks::task_input] #[derive( - Debug, - Clone, - TaskInput, - TraceRawVcs, - PartialEq, - Eq, - Hash, - ValueDebugFormat, - NonLocalValue, - OperationValue, - Encode, - Decode, + Debug, Clone, TraceRawVcs, PartialEq, Eq, Hash, ValueDebugFormat, OperationValue, Encode, Decode, )] enum EndpointSelector { RoutePageHtml(RcStr), diff --git a/crates/next-api/src/pages.rs b/crates/next-api/src/pages.rs index 39b13ba4b33d..221debced323 100644 --- a/crates/next-api/src/pages.rs +++ b/crates/next-api/src/pages.rs @@ -32,8 +32,8 @@ use next_core::{ use tracing::Instrument; use turbo_rcstr::{RcStr, rcstr}; use turbo_tasks::{ - Completion, FxIndexMap, NonLocalValue, ResolvedVc, TaskInput, ValueToString, Vc, fxindexmap, - fxindexset, trace::TraceRawVcs, + Completion, FxIndexMap, ResolvedVc, ValueToString, Vc, fxindexmap, fxindexset, + trace::TraceRawVcs, }; use turbo_tasks_fs::{ self, File, FileContent, FileSystem, FileSystemPath, FileSystemPathOption, VirtualFileSystem, @@ -588,9 +588,8 @@ struct PageEndpoint { pages_structure: ResolvedVc, } -#[derive( - Copy, Clone, PartialEq, Eq, Hash, Debug, TaskInput, TraceRawVcs, NonLocalValue, Encode, Decode, -)] +#[turbo_tasks::task_input] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TraceRawVcs, Encode, Decode)] enum PageEndpointType { Api, Html, @@ -601,14 +600,16 @@ enum PageEndpointType { SsrOnly, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TaskInput, TraceRawVcs, Encode, Decode)] +#[turbo_tasks::task_input] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TraceRawVcs, Encode, Decode)] enum SsrChunkType { Page, Data, Api, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)] +#[turbo_tasks::task_input] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] enum EmitManifests { /// Don't emit any manifests None, diff --git a/crates/next-api/src/project.rs b/crates/next-api/src/project.rs index 7ed9aeadbede..cc115ec3c748 100644 --- a/crates/next-api/src/project.rs +++ b/crates/next-api/src/project.rs @@ -36,7 +36,7 @@ use tracing::{Instrument, field::Empty}; use turbo_rcstr::{RcStr, rcstr}; use turbo_tasks::{ Completion, Completions, FxIndexMap, NonLocalValue, OperationValue, OperationVc, ReadRef, - ResolvedVc, State, TaskInput, TransientInstance, TryFlatJoinIterExt, TryJoinIterExt, Vc, + ResolvedVc, State, TransientInstance, TryFlatJoinIterExt, TryJoinIterExt, Vc, debug::ValueDebugFormat, fxindexmap, trace::TraceRawVcs, }; use turbo_tasks_env::{EnvMap, ProcessEnv}; @@ -103,17 +103,16 @@ use crate::{ versioned_content_map::VersionedContentMap, }; +#[turbo_tasks::task_input] #[derive( Debug, Serialize, Deserialize, Clone, - TaskInput, PartialEq, Eq, Hash, TraceRawVcs, - NonLocalValue, OperationValue, Encode, Decode, @@ -125,6 +124,7 @@ pub struct DraftModeOptions { pub preview_mode_signing_key: RcStr, } +#[turbo_tasks::task_input] #[derive( Debug, Default, @@ -132,12 +132,10 @@ pub struct DraftModeOptions { Deserialize, Copy, Clone, - TaskInput, PartialEq, Eq, Hash, TraceRawVcs, - NonLocalValue, OperationValue, Encode, Decode, @@ -152,18 +150,17 @@ pub struct WatchOptions { pub poll_interval: Option, } +#[turbo_tasks::task_input] #[derive( Debug, Default, Serialize, Deserialize, Clone, - TaskInput, PartialEq, Eq, Hash, TraceRawVcs, - NonLocalValue, OperationValue, Encode, Decode, @@ -175,20 +172,8 @@ pub struct DebugBuildPaths { } /// Target for HMR operations - client-side (browser) or server-side (Node.js). -#[derive( - Debug, - Default, - Copy, - Clone, - TaskInput, - PartialEq, - Eq, - Hash, - TraceRawVcs, - NonLocalValue, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] pub enum HmrTarget { #[default] Client, @@ -439,17 +424,16 @@ pub struct PartialProjectOptions { pub debug_build_paths: Option, } +#[turbo_tasks::task_input] #[derive( Debug, Serialize, Deserialize, Clone, - TaskInput, PartialEq, Eq, Hash, TraceRawVcs, - NonLocalValue, OperationValue, Encode, Decode, diff --git a/crates/next-core/src/app_structure.rs b/crates/next-core/src/app_structure.rs index 4fccb7f9c930..1016d3818bd8 100644 --- a/crates/next-core/src/app_structure.rs +++ b/crates/next-core/src/app_structure.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use tracing::Instrument; use turbo_rcstr::{RcStr, rcstr}; use turbo_tasks::{ - FxIndexMap, FxIndexSet, NonLocalValue, ResolvedVc, TaskInput, TryJoinIterExt, ValueDefault, + FxIndexMap, FxIndexSet, NonLocalValue, ResolvedVc, TryJoinIterExt, ValueDefault, ValueToStringRef, Vc, debug::ValueDebugFormat, fxindexmap, trace::TraceRawVcs, turbobail, }; use turbo_tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPath}; @@ -84,9 +84,8 @@ pub enum MetadataWithAltItem { } /// A single metadata file. -#[derive( - Clone, Debug, Hash, PartialEq, Eq, TaskInput, TraceRawVcs, NonLocalValue, Encode, Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, Hash, PartialEq, Eq, TraceRawVcs, Encode, Decode)] pub enum MetadataItem { Static { path: FileSystemPath }, Dynamic { path: FileSystemPath }, @@ -561,19 +560,8 @@ impl ValueDefault for FileSystemPathVec { } } -#[derive( - Clone, - PartialEq, - Eq, - Hash, - TraceRawVcs, - ValueDebugFormat, - Debug, - TaskInput, - NonLocalValue, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, PartialEq, Eq, Hash, TraceRawVcs, ValueDebugFormat, Debug, Encode, Decode)] pub enum Entrypoint { AppPage { pages: Vec, diff --git a/crates/next-core/src/mode.rs b/crates/next-core/src/mode.rs index f6a0496f8660..b705e92a2fa7 100644 --- a/crates/next-core/src/mode.rs +++ b/crates/next-core/src/mode.rs @@ -1,12 +1,11 @@ use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::TaskInput; use turbopack_ecmascript_runtime::RuntimeType; use crate::next_shared::webpack_rules::WebpackLoaderBuiltinCondition; /// The mode in which Next.js is running. -#[turbo_tasks::value(shared)] -#[derive(Debug, Copy, Clone, TaskInput, Ord, PartialOrd, Hash)] +#[turbo_tasks::value(shared, task_input)] +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Hash)] pub enum NextMode { /// `next dev --turbopack` Development, diff --git a/crates/next-core/src/next_app/mod.rs b/crates/next-core/src/next_app/mod.rs index 2ef5d3234f89..d205324f9ff8 100644 --- a/crates/next-core/src/next_app/mod.rs +++ b/crates/next-core/src/next_app/mod.rs @@ -14,7 +14,7 @@ use std::{ use anyhow::{Result, bail}; use bincode::{Decode, Encode}; use turbo_rcstr::RcStr; -use turbo_tasks::{NonLocalValue, TaskInput, trace::TraceRawVcs}; +use turbo_tasks::trace::TraceRawVcs; pub use crate::next_app::{ app_client_references_chunks::{ @@ -28,20 +28,8 @@ pub use crate::next_app::{ }; /// See [AppPage]. -#[derive( - Clone, - Debug, - Hash, - PartialEq, - Eq, - PartialOrd, - Ord, - TaskInput, - TraceRawVcs, - NonLocalValue, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, TraceRawVcs, Encode, Decode)] pub enum PageSegment { /// e.g. `/dashboard` Static(RcStr), @@ -133,20 +121,8 @@ impl Display for PageSegment { } } -#[derive( - Clone, - Debug, - Hash, - PartialEq, - Eq, - PartialOrd, - Ord, - TaskInput, - TraceRawVcs, - NonLocalValue, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, TraceRawVcs, Encode, Decode)] pub enum PageType { Page, Route, @@ -164,19 +140,8 @@ impl Display for PageType { /// Describes the pathname including all internal modifiers such as /// intercepting routes, parallel routes and route/page suffixes that are not /// part of the pathname. -#[derive( - Clone, - Debug, - Hash, - PartialEq, - Eq, - Default, - TaskInput, - TraceRawVcs, - NonLocalValue, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, Hash, PartialEq, Eq, Default, TraceRawVcs, Encode, Decode)] pub struct AppPage(pub Vec); impl AppPage { @@ -359,20 +324,8 @@ impl PartialOrd for AppPage { /// Path segments for a router path (not including parallel routes and groups). /// /// Also see [AppPath]. -#[derive( - Clone, - Debug, - Hash, - PartialEq, - Eq, - PartialOrd, - Ord, - TaskInput, - TraceRawVcs, - NonLocalValue, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, TraceRawVcs, Encode, Decode)] pub enum PathSegment { /// e.g. `/dashboard` Static(RcStr), @@ -412,19 +365,8 @@ impl Display for PathSegment { /// /// Does not include internal modifiers as it's the equivalent of the http /// request path. -#[derive( - Clone, - Debug, - Hash, - PartialEq, - Eq, - Default, - TaskInput, - TraceRawVcs, - NonLocalValue, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, Hash, PartialEq, Eq, Default, TraceRawVcs, Encode, Decode)] pub struct AppPath(pub Vec); impl AppPath { diff --git a/crates/next-core/src/next_client/context.rs b/crates/next-core/src/next_client/context.rs index cc8843d1f40f..2e79dfde0f3d 100644 --- a/crates/next-core/src/next_client/context.rs +++ b/crates/next-core/src/next_client/context.rs @@ -3,7 +3,7 @@ use std::collections::BTreeSet; use anyhow::Result; use bincode::{Decode, Encode}; use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::{ResolvedVc, TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks::{ResolvedVc, Vc, trace::TraceRawVcs}; use turbo_tasks_fs::FileSystemPath; use turbopack::module_options::{ CssOptionsContext, EcmascriptOptionsContext, JsxTransformOptions, ModuleRule, @@ -135,8 +135,8 @@ pub async fn get_client_compile_time_info( .await } -#[turbo_tasks::value(shared)] -#[derive(Debug, Clone, Hash, TaskInput)] +#[turbo_tasks::value(shared, task_input)] +#[derive(Debug, Clone, Hash)] pub enum ClientContextType { Pages { pages_dir: FileSystemPath }, App { app_dir: FileSystemPath }, @@ -454,7 +454,8 @@ pub async fn get_client_module_options_context( Ok(module_options_context) } -#[derive(Clone, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)] +#[turbo_tasks::task_input(contains_unresolved_vcs)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] pub struct ClientChunkingContextOptions { pub mode: Vc, pub root_path: FileSystemPath, diff --git a/crates/next-core/src/next_config.rs b/crates/next-core/src/next_config.rs index b75113053b8c..f9a3092d47f6 100644 --- a/crates/next-core/src/next_config.rs +++ b/crates/next-core/src/next_config.rs @@ -8,7 +8,7 @@ use serde_json::Value as JsonValue; use turbo_esregex::EsRegex; use turbo_rcstr::{RcStr, rcstr}; use turbo_tasks::{ - FxIndexMap, NonLocalValue, OperationValue, ResolvedVc, TaskInput, TryJoinIterExt, Vc, + FxIndexMap, NonLocalValue, OperationValue, ResolvedVc, TryJoinIterExt, Vc, debug::ValueDebugFormat, trace::TraceRawVcs, }; use turbo_tasks_env::EnvMap; @@ -350,6 +350,7 @@ pub enum OutputType { #[turbo_tasks::value(transparent)] pub struct OptionOutputType(Option); +#[turbo_tasks::task_input] #[derive( Debug, Clone, @@ -358,11 +359,9 @@ pub struct OptionOutputType(Option); PartialEq, Ord, PartialOrd, - TaskInput, TraceRawVcs, Serialize, Deserialize, - NonLocalValue, OperationValue, Encode, Decode, diff --git a/crates/next-core/src/next_edge/context.rs b/crates/next-core/src/next_edge/context.rs index c5fa24f9d275..c61a7e860c6e 100644 --- a/crates/next-core/src/next_edge/context.rs +++ b/crates/next-core/src/next_edge/context.rs @@ -1,7 +1,7 @@ use anyhow::Result; use bincode::{Decode, Encode}; use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::{ResolvedVc, TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks::{ResolvedVc, Vc, trace::TraceRawVcs}; use turbo_tasks_fs::FileSystemPath; use turbopack_browser::BrowserChunkingContext; use turbopack_core::{ @@ -183,7 +183,8 @@ pub async fn get_edge_resolve_options_context( .cell()) } -#[derive(Clone, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)] +#[turbo_tasks::task_input(contains_unresolved_vcs)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] pub struct EdgeChunkingContextOptions { pub mode: Vc, pub root_path: FileSystemPath, diff --git a/crates/next-core/src/next_font/google/options.rs b/crates/next-core/src/next_font/google/options.rs index 00d738b7e843..db0451c6edc5 100644 --- a/crates/next-core/src/next_font/google/options.rs +++ b/crates/next-core/src/next_font/google/options.rs @@ -2,9 +2,7 @@ use anyhow::{Context, Result}; use bincode::{Decode, Encode}; use serde::Deserialize; use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::{ - FxIndexMap, FxIndexSet, NonLocalValue, TaskInput, Vc, fxindexset, trace::TraceRawVcs, -}; +use turbo_tasks::{FxIndexMap, FxIndexSet, NonLocalValue, Vc, fxindexset, trace::TraceRawVcs}; use super::request::{NextFontRequest, OneOrManyStrings}; @@ -12,8 +10,8 @@ const ALLOWED_DISPLAY_VALUES: &[&str] = &["auto", "block", "swap", "fallback", " pub(super) type FontData = FxIndexMap; -#[turbo_tasks::value] -#[derive(Clone, Debug, PartialOrd, Ord, Hash, TaskInput)] +#[turbo_tasks::value(task_input)] +#[derive(Clone, Debug, PartialOrd, Ord, Hash)] pub(super) struct NextFontGoogleOptions { /// Name of the requested font from Google. Contains literal spaces. pub font_family: RcStr, @@ -44,20 +42,9 @@ impl NextFontGoogleOptions { } } +#[turbo_tasks::task_input] #[derive( - Clone, - Debug, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Deserialize, - TraceRawVcs, - NonLocalValue, - TaskInput, - Encode, - Decode, + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, TraceRawVcs, Encode, Decode, )] pub(super) enum FontWeights { Variable, diff --git a/crates/next-core/src/next_font/local/options.rs b/crates/next-core/src/next_font/local/options.rs index 9a3b6dcfa92a..afe11eb6c1c6 100644 --- a/crates/next-core/src/next_font/local/options.rs +++ b/crates/next-core/src/next_font/local/options.rs @@ -3,7 +3,7 @@ use std::{fmt::Display, str::FromStr}; use anyhow::{Context, Result}; use bincode::{Decode, Encode}; use turbo_rcstr::RcStr; -use turbo_tasks::{NonLocalValue, TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks::{Vc, trace::TraceRawVcs}; use crate::next_font::local::request::{ AdjustFontFallback, NextFontLocalDeclaration, NextFontLocalRequest, @@ -12,8 +12,8 @@ use crate::next_font::local::request::{ /// A normalized, Vc-friendly struct derived from validating and transforming /// [[NextFontLocalRequest]] -#[turbo_tasks::value] -#[derive(Clone, Debug, PartialOrd, Ord, Hash, TaskInput)] +#[turbo_tasks::value(task_input)] +#[derive(Clone, Debug, PartialOrd, Ord, Hash)] pub(super) struct NextFontLocalOptions { pub fonts: FontDescriptors, pub default_weight: Option, @@ -52,20 +52,8 @@ impl NextFontLocalOptions { /// Describes an individual font file's path, weight, style, etc. Derived from /// the `src` field or top-level object provided by the user -#[derive( - Clone, - Debug, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - TraceRawVcs, - NonLocalValue, - TaskInput, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TraceRawVcs, Encode, Decode)] pub(super) struct FontDescriptor { pub weight: Option, pub style: Option, @@ -94,20 +82,8 @@ impl FontDescriptor { } } -#[derive( - Clone, - Debug, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - TraceRawVcs, - NonLocalValue, - TaskInput, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TraceRawVcs, Encode, Decode)] pub(super) enum FontDescriptors { /// `One` is a special case when the user did not provide a `src` field and /// instead included font path, weight etc in the top-level object: in @@ -117,20 +93,8 @@ pub(super) enum FontDescriptors { Many(Vec), } -#[derive( - Clone, - Debug, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - TraceRawVcs, - NonLocalValue, - TaskInput, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TraceRawVcs, Encode, Decode)] pub(super) enum FontWeight { Variable(RcStr, RcStr), Fixed(RcStr), diff --git a/crates/next-core/src/next_font/local/request.rs b/crates/next-core/src/next_font/local/request.rs index aaa2442a895a..f0e6a65276cc 100644 --- a/crates/next-core/src/next_font/local/request.rs +++ b/crates/next-core/src/next_font/local/request.rs @@ -1,7 +1,7 @@ use bincode::{Decode, Encode}; use serde::{Deserialize, Serialize}; use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::{NonLocalValue, TaskInput, trace::TraceRawVcs}; +use turbo_tasks::trace::TraceRawVcs; /// The top-most structure encoded into the query param in requests to /// `next/font/local` generated by the next/font swc transform. e.g. @@ -13,20 +13,9 @@ pub(super) struct NextFontLocalRequest { pub variable_name: RcStr, } +#[turbo_tasks::task_input] #[derive( - Clone, - Debug, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - TaskInput, - Deserialize, - TraceRawVcs, - NonLocalValue, - Encode, - Decode, + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, TraceRawVcs, Encode, Decode, )] pub(super) struct NextFontLocalDeclaration { pub prop: RcStr, @@ -68,6 +57,7 @@ pub(super) struct SrcDescriptor { } /// The user's desired fallback font +#[turbo_tasks::task_input] #[derive( Clone, Debug, @@ -79,8 +69,6 @@ pub(super) struct SrcDescriptor { Eq, Serialize, TraceRawVcs, - NonLocalValue, - TaskInput, Encode, Decode, )] diff --git a/crates/next-core/src/next_image/module.rs b/crates/next-core/src/next_image/module.rs index a202d4f6c273..ea00282e80ac 100644 --- a/crates/next-core/src/next_image/module.rs +++ b/crates/next-core/src/next_image/module.rs @@ -1,7 +1,7 @@ use anyhow::{Result, bail}; use bincode::{Decode, Encode}; use turbo_rcstr::rcstr; -use turbo_tasks::{NonLocalValue, ResolvedVc, TaskInput, Vc, fxindexmap, trace::TraceRawVcs}; +use turbo_tasks::{ResolvedVc, Vc, fxindexmap, trace::TraceRawVcs}; use turbopack::{ModuleAssetContext, module_options::CustomModuleType}; use turbopack_core::{ context::AssetContext, module::Module, reference_type::ReferenceType, source::Source, @@ -11,21 +11,8 @@ use turbopack_static::ecma::StaticUrlJsModule; use super::source_asset::StructuredImageFileSource; -#[derive( - Eq, - PartialEq, - Clone, - Copy, - Debug, - PartialOrd, - Ord, - Hash, - TaskInput, - TraceRawVcs, - NonLocalValue, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Eq, PartialEq, Clone, Copy, Debug, PartialOrd, Ord, Hash, TraceRawVcs, Encode, Decode)] pub enum BlurPlaceholderMode { /// Do not generate a blur placeholder at all. None, diff --git a/crates/next-core/src/next_manifests/mod.rs b/crates/next-core/src/next_manifests/mod.rs index 77f0c9468689..615091a2a808 100644 --- a/crates/next-core/src/next_manifests/mod.rs +++ b/crates/next-core/src/next_manifests/mod.rs @@ -8,8 +8,7 @@ use bincode::{Decode, Encode}; use serde::{Deserialize, Serialize}; use turbo_rcstr::RcStr; use turbo_tasks::{ - FxIndexMap, NonLocalValue, ReadRef, ResolvedVc, TaskInput, TryFlatJoinIterExt, TryJoinIterExt, - Vc, trace::TraceRawVcs, + FxIndexMap, ReadRef, ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, Vc, trace::TraceRawVcs, }; use turbo_tasks_fs::{File, FileContent, FileSystemPath}; use turbopack_core::{ @@ -279,6 +278,7 @@ impl Default for MiddlewaresManifest { } } +#[turbo_tasks::task_input] #[derive( Debug, Clone, @@ -287,11 +287,9 @@ impl Default for MiddlewaresManifest { PartialEq, Ord, PartialOrd, - TaskInput, TraceRawVcs, Serialize, Deserialize, - NonLocalValue, Encode, Decode, )] @@ -462,6 +460,7 @@ pub enum ActionManifestModuleId<'a> { Number(u64), } +#[turbo_tasks::task_input] #[derive( Debug, Copy, @@ -471,11 +470,9 @@ pub enum ActionManifestModuleId<'a> { PartialEq, Ord, PartialOrd, - TaskInput, TraceRawVcs, Serialize, Deserialize, - NonLocalValue, Encode, Decode, )] diff --git a/crates/next-core/src/next_server/context.rs b/crates/next-core/src/next_server/context.rs index a42a8dc7a736..30aa3f38ca5a 100644 --- a/crates/next-core/src/next_server/context.rs +++ b/crates/next-core/src/next_server/context.rs @@ -3,7 +3,7 @@ use std::collections::BTreeSet; use anyhow::{Result, bail}; use bincode::{Decode, Encode}; use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::{ResolvedVc, TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks::{ResolvedVc, Vc, trace::TraceRawVcs}; use turbo_tasks_fs::FileSystemPath; use turbopack::{ module_options::{ @@ -78,8 +78,8 @@ use crate::{ }, }; -#[turbo_tasks::value(shared)] -#[derive(Debug, Clone, Hash, TaskInput)] +#[turbo_tasks::value(shared, task_input)] +#[derive(Debug, Clone, Hash)] pub enum ServerContextType { Pages { pages_dir: FileSystemPath, @@ -1002,7 +1002,8 @@ fn client_disallowed_directive_transform_plugin(error_proxy_module: RcStr) -> Vc )) as Box) } -#[derive(Clone, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)] +#[turbo_tasks::task_input(contains_unresolved_vcs)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] pub struct ServerChunkingContextOptions { pub mode: Vc, pub root_path: FileSystemPath, diff --git a/crates/next-core/src/next_shared/transforms/next_strip_page_exports.rs b/crates/next-core/src/next_shared/transforms/next_strip_page_exports.rs index 2eb4a1a20e3d..4fdd00768740 100644 --- a/crates/next-core/src/next_shared/transforms/next_strip_page_exports.rs +++ b/crates/next-core/src/next_shared/transforms/next_strip_page_exports.rs @@ -6,7 +6,7 @@ use next_custom_transforms::transforms::strip_page_exports::{ }; use swc_core::ecma::ast::Program; use turbo_rcstr::RcStr; -use turbo_tasks::{ResolvedVc, TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks::{ResolvedVc, Vc, trace::TraceRawVcs}; use turbo_tasks_fs::FileSystemPath; use turbopack::module_options::{ModuleRule, ModuleRuleEffect, RuleCondition}; use turbopack_ecmascript::{ @@ -16,7 +16,8 @@ use turbopack_ecmascript::{ use super::module_rule_match_js_no_url; /// A [`TaskInput`]-compatible mirror of [`ExportFilter`]. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)] +#[turbo_tasks::task_input] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] enum ExportFilterInput { StripDataExports, StripDefaultExport, diff --git a/crates/next-core/src/next_shared/transforms/server_actions.rs b/crates/next-core/src/next_shared/transforms/server_actions.rs index 35e43e3dcc60..f391173fd26b 100644 --- a/crates/next-core/src/next_shared/transforms/server_actions.rs +++ b/crates/next-core/src/next_shared/transforms/server_actions.rs @@ -6,7 +6,7 @@ use next_custom_transforms::transforms::server_actions::{ }; use swc_core::{common::FileName, ecma::ast::Program}; use turbo_rcstr::RcStr; -use turbo_tasks::{ResolvedVc, TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks::{ResolvedVc, Vc, trace::TraceRawVcs}; use turbopack::module_options::{ModuleRule, ModuleRuleEffect}; use turbopack_ecmascript::{ CustomTransformer, EcmascriptInputTransform, TransformContext, TransformPlugin, @@ -15,7 +15,8 @@ use turbopack_ecmascript::{ use super::module_rule_match_js_no_url; use crate::{mode::NextMode, next_config::CacheKinds}; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)] +#[turbo_tasks::task_input] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] pub enum ActionsTransform { /// Browser and SSR Client, diff --git a/crates/next-core/src/next_shared/transforms/swc_ecma_transform_plugins.rs b/crates/next-core/src/next_shared/transforms/swc_ecma_transform_plugins.rs index 250fdcb6a7dd..f2b63033fbc9 100644 --- a/crates/next-core/src/next_shared/transforms/swc_ecma_transform_plugins.rs +++ b/crates/next-core/src/next_shared/transforms/swc_ecma_transform_plugins.rs @@ -26,7 +26,7 @@ impl std::hash::Hash for JsonValue { } // Manual impl because `serde_json::Value` doesn't implement `TaskInput`, but `JsonValue` can -// never contain any `Vc` types, so `is_transient` is always `false`. +// never contain any `Vc` types. impl turbo_tasks::TaskInput for JsonValue { fn is_transient(&self) -> bool { false diff --git a/crates/next-core/src/next_shared/webpack_rules/mod.rs b/crates/next-core/src/next_shared/webpack_rules/mod.rs index 7733e2412366..9417df20e615 100644 --- a/crates/next-core/src/next_shared/webpack_rules/mod.rs +++ b/crates/next-core/src/next_shared/webpack_rules/mod.rs @@ -5,7 +5,7 @@ use async_trait::async_trait; use bincode::{Decode, Encode}; use serde::Deserialize; use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::{NonLocalValue, OperationValue, ResolvedVc, TaskInput, Vc, trace::TraceRawVcs}; +use turbo_tasks::{OperationValue, ResolvedVc, Vc, trace::TraceRawVcs}; use turbo_tasks_fs::FileSystemPath; use turbopack::module_options::{ WebpackLoaderBuiltinConditionSet, WebpackLoaderBuiltinConditionSetMatch, WebpackLoadersOptions, @@ -33,6 +33,7 @@ pub(crate) mod sass; // // Note: Sets of conditions could be stored more efficiently as a bitset, but it's probably not used // in enough places for it to matter. +#[turbo_tasks::task_input] #[derive( Copy, Clone, @@ -43,9 +44,7 @@ pub(crate) mod sass; Ord, Hash, Deserialize, - TaskInput, TraceRawVcs, - NonLocalValue, OperationValue, Encode, Decode, diff --git a/crates/next-core/src/segment_config.rs b/crates/next-core/src/segment_config.rs index 08850253ae3d..0040d4e41ac7 100644 --- a/crates/next-core/src/segment_config.rs +++ b/crates/next-core/src/segment_config.rs @@ -18,7 +18,7 @@ use swc_core::{ }; use turbo_rcstr::{RcStr, rcstr}; use turbo_tasks::{ - NonLocalValue, ResolvedVc, TaskInput, TryJoinIterExt, ValueDefault, Vc, trace::TraceRawVcs, + NonLocalValue, ResolvedVc, TryJoinIterExt, ValueDefault, Vc, trace::TraceRawVcs, util::WrapFuture, }; use turbo_tasks_fs::FileSystemPath; @@ -288,9 +288,8 @@ impl Issue for NextSegmentConfigParsingIssue { } } -#[derive( - Debug, Clone, Copy, PartialEq, Eq, Hash, TaskInput, NonLocalValue, TraceRawVcs, Encode, Decode, -)] +#[turbo_tasks::task_input] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] pub enum ParseSegmentMode { Base, // Disallows "use client + generateStatic" and ignores/warns about `export const config` diff --git a/crates/next-core/src/util.rs b/crates/next-core/src/util.rs index d81461b51733..d3fa8b72123e 100644 --- a/crates/next-core/src/util.rs +++ b/crates/next-core/src/util.rs @@ -5,9 +5,7 @@ use bincode::{Decode, Encode}; use next_taskless::{expand_next_js_template, expand_next_js_template_no_imports}; use serde::{Deserialize, de::DeserializeOwned}; use turbo_rcstr::{RcStr, rcstr}; -use turbo_tasks::{ - FxIndexMap, NonLocalValue, TaskInput, Vc, fxindexset, trace::TraceRawVcs, turbobail, -}; +use turbo_tasks::{FxIndexMap, NonLocalValue, Vc, fxindexset, trace::TraceRawVcs, turbobail}; use turbo_tasks_fs::{File, FileContent, FileJsonContent, FileSystem, FileSystemPath, rope::Rope}; use turbopack::module_options::RuleCondition; use turbopack_core::{ @@ -205,7 +203,8 @@ pub fn free_var_references_with_vercel_system_env_warnings( FreeVarReferences(entries) } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)] +#[turbo_tasks::task_input] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TraceRawVcs, Encode, Decode)] pub enum PathType { PagesPage, PagesApi, @@ -327,6 +326,7 @@ pub fn pages_function_name(page: impl Display) -> String { format!("pages{page}") } +#[turbo_tasks::task_input] #[derive( Default, PartialEq, @@ -339,8 +339,6 @@ pub fn pages_function_name(page: impl Display) -> String { Hash, PartialOrd, Ord, - TaskInput, - NonLocalValue, Encode, Decode, )] diff --git a/crates/next-napi-bindings/src/next_api/project.rs b/crates/next-napi-bindings/src/next_api/project.rs index c6d0d1cfcc67..9a13abbfb130 100644 --- a/crates/next-napi-bindings/src/next_api/project.rs +++ b/crates/next-napi-bindings/src/next_api/project.rs @@ -47,9 +47,9 @@ use tracing::Instrument; use tracing_subscriber::{Registry, layer::SubscriberExt, util::SubscriberInitExt}; use turbo_rcstr::{RcStr, rcstr}; use turbo_tasks::{ - Effects, FxIndexSet, NonLocalValue, OperationValue, OperationVc, PrettyPrintError, ReadRef, - ResolvedVc, TaskInput, TransientInstance, TryJoinIterExt, TurboTasksApi, TurboTasksCallApi, - UpdateInfo, Vc, mark_top_level_task, + Effects, FxIndexSet, OperationValue, OperationVc, PrettyPrintError, ReadRef, ResolvedVc, + TransientInstance, TryJoinIterExt, TurboTasksApi, TurboTasksCallApi, UpdateInfo, Vc, + mark_top_level_task, message_queue::{CompilationEvent, Severity}, take_effects, trace::TraceRawVcs, @@ -1041,20 +1041,8 @@ pub struct NapiDebugBuildPaths { pub pages: Vec, } -#[derive( - Clone, - Copy, - Debug, - Eq, - Hash, - NonLocalValue, - OperationValue, - PartialEq, - TaskInput, - TraceRawVcs, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Copy, Debug, Eq, Hash, OperationValue, PartialEq, TraceRawVcs, Encode, Decode)] enum EntrypointsWritePhase { All, NonDeferred, @@ -2181,19 +2169,8 @@ pub fn project_compilation_events_subscribe( } #[napi(object)] -#[derive( - Clone, - Debug, - Eq, - Hash, - NonLocalValue, - OperationValue, - PartialEq, - TaskInput, - TraceRawVcs, - Encode, - Decode, -)] +#[turbo_tasks::task_input] +#[derive(Clone, Debug, Eq, Hash, OperationValue, PartialEq, TraceRawVcs, Encode, Decode)] pub struct StackFrame { pub is_server: bool, pub is_ignored: Option, diff --git a/lerna.json b/lerna.json index c30bc6ca5735..1ccef83bf6c9 100644 --- a/lerna.json +++ b/lerna.json @@ -15,5 +15,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "16.3.0-canary.39" + "version": "16.3.0-canary.40" } \ No newline at end of file diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 6b3d74a2136b..70bccc495c03 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index b459fc1c47ef..1f9aad1ce1b3 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "description": "ESLint configuration used by Next.js.", "license": "MIT", "repository": { @@ -12,7 +12,7 @@ "dist" ], "dependencies": { - "@next/eslint-plugin-next": "16.3.0-canary.39", + "@next/eslint-plugin-next": "16.3.0-canary.40", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json index 83e94db26489..de4c6ae5a24e 100644 --- a/packages/eslint-plugin-internal/package.json +++ b/packages/eslint-plugin-internal/package.json @@ -1,7 +1,7 @@ { "name": "@next/eslint-plugin-internal", "private": true, - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "description": "ESLint plugin for working on Next.js.", "exports": { ".": "./src/eslint-plugin-internal.js" diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 88d12d1c9934..016e047ae85d 100644 --- a/packages/eslint-plugin-next/package.json +++ b/packages/eslint-plugin-next/package.json @@ -1,6 +1,6 @@ { "name": "@next/eslint-plugin-next", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "description": "ESLint plugin for Next.js.", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/font/package.json b/packages/font/package.json index 482d28f2b295..875b0821868f 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,7 +1,7 @@ { "name": "@next/font", "private": true, - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "repository": { "url": "vercel/next.js", "directory": "packages/font" diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index 96be004dce7c..fd20014c8cc4 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 5a95bca18fb9..1f5ce1d2a0ac 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "license": "MIT", "repository": { "type": "git", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 647ae69d81f8..421fc4e243a4 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index c15efc9c7522..c9d6a06e2a62 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-playwright/package.json b/packages/next-playwright/package.json index 8d04899e7d7e..37d2fd444858 100644 --- a/packages/next-playwright/package.json +++ b/packages/next-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@next/playwright", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "repository": { "url": "vercel/next.js", "directory": "packages/next-playwright" diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index ddeaf716995f..17ff46760215 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "repository": { "url": "vercel/next.js", "directory": "packages/next-plugin-storybook" diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json index 3fd8b9640359..8e737f9a412f 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)", "main": "dist/polyfill-module.js", "license": "MIT", diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json index ff04c74fc26f..6346c75e1db7 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-routing/package.json b/packages/next-routing/package.json index 2aaf6ac757b1..1546528a3618 100644 --- a/packages/next-routing/package.json +++ b/packages/next-routing/package.json @@ -1,6 +1,6 @@ { "name": "@next/routing", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "keywords": [ "react", "next", diff --git a/packages/next-rspack/package.json b/packages/next-rspack/package.json index f5d35d42debe..f852265eeef0 100644 --- a/packages/next-rspack/package.json +++ b/packages/next-rspack/package.json @@ -1,6 +1,6 @@ { "name": "next-rspack", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "repository": { "url": "vercel/next.js", "directory": "packages/next-rspack" diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index 230836278308..617d2519e925 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "private": true, "files": [ "native/" diff --git a/packages/next/.storybook/fixtures/errors.ts b/packages/next/.storybook/fixtures/errors.ts index dadeca6656cb..04e6b98bea9d 100644 --- a/packages/next/.storybook/fixtures/errors.ts +++ b/packages/next/.storybook/fixtures/errors.ts @@ -360,7 +360,7 @@ export const instantRuntimeDataErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/01-cookies-body": Next.js encountered runtime data during the initial render.\n\n`cookies()`, `headers()`, `params`, or `searchParams` accessed outside of `` prevents the route from being prerendered, blocking navigation and leading to a slower user experience.\n\nWays to fix this:\n - Provide a placeholder with `` around the data access\n - Use `generateStaticParams` to make route params static\n - Set `export const instant = false` to allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-route' + 'Route "/01-cookies-body": Next.js encountered runtime data during prerendering.\n\n`cookies()`, `headers()`, `params`, or `searchParams` accessed outside of `` prevents the route from being prerendered, blocking the page load and leading to a slower user experience.\n\nWays to fix this:\n - [stream] Provide a placeholder with `` around the data access\n - [cache] If the runtime data is `params` and they\'re known, prerender them with `generateStaticParams`\n - [block] Set `export const unstable_instant = false` to silence this warning and allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-route' ), { __NEXT_ERROR_CODE: 'E1221' } ), @@ -388,7 +388,7 @@ export const instantUncachedDataErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/06-uncached-fetch-body": Next.js encountered uncached data during the initial render.\n\n`fetch(...)` or `connection()` accessed outside of `` prevents the route from being prerendered, blocking navigation and leading to a slower user experience.\n\nWays to fix this:\n - Cache the data access with `"use cache"`\n - Provide a placeholder with `` around the data access\n - Set `export const instant = false` to allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-route' + 'Route "/06-uncached-fetch-body": Next.js encountered uncached data during prerendering.\n\n`fetch(...)` or `connection()` accessed outside of `` prevents the route from being prerendered, blocking the page load and leading to a slower user experience.\n\nWays to fix this:\n - [cache] Cache the data access with `"use cache"`\n - [stream] Provide a placeholder with `` around the data access\n - [block] Set `export const unstable_instant = false` to silence this warning and allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-route' ), { __NEXT_ERROR_CODE: 'E1220' } ), @@ -416,7 +416,7 @@ export const instantViewportErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/14-cookies-in-viewport": Next.js encountered runtime data in `generateViewport()`.\n\n`cookies()`, `headers()`, `params`, or `searchParams` in `generateViewport()` prevents the page from being prerendered, leading to a slower user experience.\n\nWays to fix this:\n - Use a static viewport export instead of `generateViewport()`\n - Wrap your document `` in ``\n - Set `export const instant = false` to allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/next-prerender-dynamic-viewport' + 'Route "/14-cookies-in-viewport": Next.js encountered runtime data in `generateViewport()`.\n\n`cookies()`, `headers()`, `params`, or `searchParams` in `generateViewport()` prevents the page from being prerendered, leading to a slower user experience.\n\nWays to fix this:\n - [static] Use a static viewport export instead of `generateViewport()`\n - [block] Set `export const unstable_instant = false` to silence this warning and allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-prerender-viewport-runtime' ), { __NEXT_ERROR_CODE: 'E1208' } ), @@ -447,7 +447,7 @@ export const instantViewportUncachedErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/15-fetch-in-viewport": Next.js encountered uncached data in `generateViewport()`.\n\n`fetch(...)` or `connection()` in `generateViewport()` prevents the page from being prerendered, leading to a slower user experience.\n\nWays to fix this:\n - Cache the viewport data with `"use cache"` in `generateViewport()`\n - Wrap your document `` in ``\n - Set `export const instant = false` to allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/next-prerender-dynamic-viewport' + 'Route "/15-fetch-in-viewport": Next.js encountered uncached data in `generateViewport()`.\n\n`fetch(...)` or `connection()` in `generateViewport()` prevents the page from being prerendered, leading to a slower user experience.\n\nWays to fix this:\n - [cache] Cache the viewport data with `"use cache"` in `generateViewport()`\n - [block] Set `export const unstable_instant = false` to silence this warning and allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-prerender-viewport-dynamic' ), { __NEXT_ERROR_CODE: 'E1210' } ), @@ -477,7 +477,7 @@ export const instantMetadataErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/12-cookies-in-metadata": Next.js encountered runtime data in `generateMetadata()`.\n\nThis route\'s metadata is blocked, but the rest of its content can be prerendered. `cookies()`, `headers()`, `params`, or `searchParams` accessed in `generateMetadata()` cause it to run dynamically.\n\nWays to fix this:\n - Use a static metadata export instead of `generateMetadata()`\n - Add a dynamic data access (e.g. `await connection()`) to the page to render it at request time\n\nLearn more: https://nextjs.org/docs/messages/next-prerender-dynamic-metadata' + 'Route "/12-cookies-in-metadata": Next.js encountered runtime data in `generateMetadata()`.\n\nThis route\'s metadata is blocked, but the rest of its content can be prerendered. `cookies()`, `headers()`, `params`, or `searchParams` accessed in `generateMetadata()` cause it to run dynamically.\n\nWays to fix this:\n - [static] Use a static metadata export instead of `generateMetadata()`\n - [dynamic] Render a marker component that calls `await connection()` inside `` on the page\n\nLearn more: https://nextjs.org/docs/messages/blocking-prerender-metadata-runtime' ), { __NEXT_ERROR_CODE: 'E1230' } ), @@ -508,9 +508,9 @@ export const instantMetadataUncachedErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/13-fetch-in-metadata": Next.js encountered uncached data in `generateMetadata()`.\n\nThis route\'s metadata is blocked, but the rest of its content can be prerendered. `fetch(...)` or `connection()` accessed in `generateMetadata()` cause it to run dynamically.\n\nWays to fix this:\n - Cache the metadata with `"use cache"` in `generateMetadata()`\n - Add a dynamic data access (e.g. `await connection()`) to the page to render it at request time\n\nLearn more: https://nextjs.org/docs/messages/next-prerender-dynamic-metadata' + 'Route "/13-fetch-in-metadata": Next.js encountered uncached data in `generateMetadata()`.\n\nThis route\'s metadata is blocked, but the rest of its content can be prerendered. `fetch(...)` or `connection()` accessed in `generateMetadata()` cause it to run dynamically.\n\nWays to fix this:\n - [cache] Cache the metadata with `"use cache"` in `generateMetadata()`\n - [dynamic] Render a marker component that calls `await connection()` inside `` on the page\n\nLearn more: https://nextjs.org/docs/messages/blocking-prerender-metadata-dynamic' ), - { __NEXT_ERROR_CODE: 'E1231' } + { __NEXT_ERROR_CODE: 'E1308' } ), frames: createStoryFrames({ reason: @@ -539,7 +539,7 @@ export const instantCurrentTimeErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/39-date-now-no-instant": Next.js encountered `Date.now()` without an explicit rendering intent.\n\nThis value can change between renders, so it must be either prerendered or computed later.\n\nWays to fix this:\n - Render at request time by adding a dynamic data access (e.g. `await connection()`) before this call\n - Prerender and cache the value with `"use cache"`\n - Render the value on the client with `"use client"`\n - Measure elapsed time with `performance.now()` instead of `Date.now()`\n\nLearn more: https://nextjs.org/docs/messages/next-prerender-current-time' + 'Route "/39-date-now-no-instant": Next.js encountered `Date.now()` without an explicit rendering intent.\n\nThis value can change between renders, so it must be either prerendered or computed later.\n\nWays to fix this:\n - [dynamic] Render at request time by adding a dynamic data access (e.g. `await connection()`) before this call\n - [cache] Prerender and cache the value with `"use cache"`\n - [client] Render the value on the client with `"use client"`\n - Measure elapsed time with `performance.now()` instead of `Date.now()`\n\nLearn more: https://nextjs.org/docs/messages/blocking-prerender-current-time' ), { __NEXT_ERROR_CODE: 'E1247' } ), @@ -568,7 +568,7 @@ export const instantMathRandomErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/38-math-random-no-instant": Next.js encountered `Math.random()` without an explicit rendering intent.\n\nThis value can change between renders, so it must be either prerendered or computed later.\n\nWays to fix this:\n - Render at request time by adding a dynamic data access (e.g. `await connection()`) before this call\n - Prerender and cache the value with `"use cache"`\n - Render the value on the client with `"use client"`\n\nLearn more: https://nextjs.org/docs/messages/next-prerender-random' + 'Route "/38-math-random-no-instant": Next.js encountered `Math.random()` without an explicit rendering intent.\n\nThis value can change between renders, so it must be either prerendered or computed later.\n\nWays to fix this:\n - [dynamic] Render at request time by adding a dynamic data access (e.g. `await connection()`) before this call\n - [cache] Prerender and cache the value with `"use cache"`\n - [client] Render the value on the client with `"use client"`\n\nLearn more: https://nextjs.org/docs/messages/blocking-prerender-random' ), { __NEXT_ERROR_CODE: 'E1247' } ), @@ -597,7 +597,7 @@ export const instantCryptoRandomUUIDErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/40-crypto-random-no-instant": Next.js encountered `crypto.randomUUID()` without an explicit rendering intent.\n\nThis value can change between renders, so it must be either prerendered or computed later.\n\nWays to fix this:\n - Render at request time by adding a dynamic data access (e.g. `await connection()`) before this call\n - Prerender and cache the value with `"use cache"`\n - Render the value on the client with `"use client"`\n\nLearn more: https://nextjs.org/docs/messages/next-prerender-crypto' + 'Route "/40-crypto-random-no-instant": Next.js encountered `crypto.randomUUID()` without an explicit rendering intent.\n\nThis value can change between renders, so it must be either prerendered or computed later.\n\nWays to fix this:\n - [dynamic] Render at request time by adding a dynamic data access (e.g. `await connection()`) before this call\n - [cache] Prerender and cache the value with `"use cache"`\n - [client] Render the value on the client with `"use client"`\n\nLearn more: https://nextjs.org/docs/messages/blocking-prerender-crypto' ), { __NEXT_ERROR_CODE: 'E1247' } ), @@ -626,7 +626,7 @@ export const instantClientMathRandomErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/44-client-math-random-no-suspense": Next.js encountered `Math.random()` in a Client Component.\n\nThis value would be evaluated during the prerender and fixed at build time, instead of recomputed on each visit.\n\nWays to fix this:\n - Wrap the Client Component in ``\n - Move the read into a `useEffect` or event handler\n\nLearn more: https://nextjs.org/docs/messages/next-prerender-random-client' + 'Route "/44-client-math-random-no-suspense": Next.js encountered `Math.random()` in a Client Component.\n\nThis value would be evaluated during the prerender and fixed at build time, instead of recomputed on each visit.\n\nWays to fix this:\n - [stream] Wrap the Client Component in ``\n - [defer] Move the read into a `useEffect` or event handler\n\nLearn more: https://nextjs.org/docs/messages/blocking-prerender-random-client' ), { __NEXT_ERROR_CODE: 'E1228' } ), @@ -655,7 +655,7 @@ export const instantUnrenderedSegmentErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/81-instant-wrapper-unrendered-segment/trigger": Could not validate that a segment in your UI has instant navigation.\n\nThis segment was dropped from rendering. Issues that would prevent instant navigation will go undetected.\n\nDropped segment:\n test-app/app/81-instant-wrapper-unrendered-segment/trigger/page.tsx\n\nWays to fix this:\n - Render the dropped segment\n - Set `export const instant = false` on the dropped segment to skip validation\n\nLearn more: https://nextjs.org/docs/messages/unrendered-instant-segment' + 'Route "/81-instant-wrapper-unrendered-segment/trigger": Could not validate that a segment in your UI has instant navigation.\n\nThis segment was dropped from rendering. Issues that would prevent instant navigation will go undetected.\n\nDropped segment:\n test-app/app/81-instant-wrapper-unrendered-segment/trigger/page.tsx\n\nWays to fix this:\n - [render] Render the dropped segment\n - [ignore] Set `export const unstable_instant = false` on the dropped segment to skip validation\n\nLearn more: https://nextjs.org/docs/messages/instant-unrendered-segment' ), { __NEXT_ERROR_CODE: 'E1286' } ), @@ -672,7 +672,7 @@ export const mixedIssueAndInsightErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/nav-cookies-under-suspense": Next.js encountered runtime data during the initial render or a navigation.\n\n`cookies()`, `headers()`, `params`, or `searchParams` accessed under `` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\n\nWays to fix this:\n - Use `generateStaticParams` to make route params static\n - Provide a placeholder with `` around the data access\n - Set `export const instant = false` to allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-route' + 'Route "/nav-cookies-under-suspense": Next.js encountered runtime data during prerendering or a navigation.\n\n`cookies()`, `headers()`, `params`, or `searchParams` accessed outside of `` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\n\nWays to fix this:\n - [stream] Provide a placeholder with `` around the data access\n - [cache] If the runtime data is `params` and they\'re known, prerender them with `generateStaticParams`\n - [block] Set `export const unstable_instant = false` to silence this warning and allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-route' ), { __NEXT_ERROR_CODE: 'E1247' } ), @@ -697,7 +697,7 @@ export const mixedIssueAndInsightErrors: ReadyRuntimeError[] = [ runtime: true, error: Object.assign( new Error( - 'Route "/nav-fetch-under-suspense": Next.js encountered uncached data during the initial render or a navigation.\n\n`fetch(...)` or `connection()` accessed under `` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\n\nWays to fix this:\n - Cache the data access with `"use cache"`\n - Provide a placeholder with `` around the data access\n - Set `export const instant = false` to allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-route' + 'Route "/nav-fetch-under-suspense": Next.js encountered uncached data during prerendering or a navigation.\n\n`fetch(...)` or `connection()` accessed outside of `` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\n\nWays to fix this:\n - [cache] Cache the data access with `"use cache"`\n - [stream] Provide a placeholder with `` around the data access\n - [block] Set `export const unstable_instant = false` to silence this warning and allow a blocking route\n\nLearn more: https://nextjs.org/docs/messages/blocking-route' ), { __NEXT_ERROR_CODE: 'E1246' } ), diff --git a/packages/next/errors.json b/packages/next/errors.json index 7e6b987acf5e..b190b445702e 100644 --- a/packages/next/errors.json +++ b/packages/next/errors.json @@ -1285,7 +1285,20 @@ "1284": "Cache Components error recovery expected an original prerender store", "1285": "Cache Components error recovery expected an original resume data cache", "1286": "Route \"%s\": Could not validate that a segment in your UI has instant navigation.", - "1287": "A render that hasn't started yet cannot be abandoned", - "1288": "Cannot determine late/early stage before starting the render", - "1289": "Attempted to advance to stage %s but the render is limited to %s" + "1287": "Route \"%s\": Next.js encountered the unstable value %s in a Client Component.\\n\\nThis value would be evaluated during the prerender, instead of recomputed on each visit.\\n\\nWays to fix this:\\n - [stream] Wrap the Client Component in \\`\\`\\n %s#wrap-in-or-move-into-suspense\\n - [defer] Move the read into a \\`useEffect\\` or event handler\\n %s#move-into-effect-or-event-handler%s", + "1288": "Route \"%s\": Next.js encountered runtime data in \\`generateMetadata()\\`.\\n\\nThis route's metadata is blocked, but the rest of its content can be prerendered. \\`cookies()\\`, \\`headers()\\`, \\`params\\`, or \\`searchParams\\` accessed in \\`generateMetadata()\\` cause it to run dynamically.\\n\\nWays to fix this:\\n - [static] Use a static metadata export instead of \\`generateMetadata()\\`\\n https://nextjs.org/docs/messages/blocking-prerender-metadata-runtime#use-static-metadata\\n - [dynamic] Render a marker component that calls \\`await connection()\\` inside \\`\\` on the page\\n https://nextjs.org/docs/messages/blocking-prerender-metadata-runtime#mark-the-route-as-dynamic", + "1289": "Route \"%s\": Next.js encountered uncached data in \\`generateViewport()\\`.\\n\\n\\`fetch(...)\\` or \\`connection()\\` in \\`generateViewport()\\` prevents the page from being prerendered, leading to a slower user experience.\\n\\nWays to fix this:\\n - [cache] Cache the viewport data with \\`\"use cache\"\\` in \\`generateViewport()\\`\\n https://nextjs.org/docs/messages/blocking-prerender-viewport-dynamic#cache-the-viewport-data\\n - [block] Set \\`export const unstable_instant = false\\` to silence this warning and allow a blocking route\\n https://nextjs.org/docs/messages/blocking-prerender-viewport-dynamic#allow-blocking-route", + "1290": "Route \"%s\": Next.js encountered uncached data during prerendering.\\n\\n\\`fetch(...)\\` or \\`connection()\\` accessed outside of \\`\\` prevents the route from being prerendered, blocking the page load and leading to a slower user experience.\\n\\nWays to fix this:\\n - [cache] Cache the data access with \\`\"use cache\"\\`\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#cache-the-component-or-data\\n - [stream] Provide a placeholder with \\`\\` around the data access\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#wrap-in-or-move-into-suspense\\n - [block] Set \\`export const unstable_instant = false\\` to silence this warning and allow a blocking route\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#allow-blocking-route", + "1291": "Route \"%s\": Next.js encountered uncached or runtime data in \\`generateViewport()\\`.\\n\\nThis prevents the page from being prerendered, leading to a slower user experience.\\n\\nWays to fix this:\\n - [static] Use a static viewport export instead of \\`generateViewport()\\`\\n https://nextjs.org/docs/messages/blocking-prerender-viewport-runtime#use-static-viewport\\n - [cache] Cache the viewport data with \\`\"use cache\"\\` in \\`generateViewport()\\`\\n https://nextjs.org/docs/messages/blocking-prerender-viewport-dynamic#cache-the-viewport-data\\n - [block] Set \\`export const unstable_instant = false\\` to silence this warning and allow a blocking route\\n https://nextjs.org/docs/messages/blocking-prerender-viewport-dynamic#allow-blocking-route", + "1292": "Route \"%s\": Next.js encountered uncached data in \\`generateMetadata()\\`.\\n\\nThis route's metadata is blocked, but the rest of its content can be prerendered. \\`fetch(...)\\` or \\`connection()\\` accessed in \\`generateMetadata()\\` cause it to run dynamically.\\n\\nWays to fix this:\\n - [cache] Cache the metadata with \\`\"use cache\"\\` in \\`generateMetadata()\\`\\n https://nextjs.org/docs/messages/blocking-prerender-metadata-dynamic#cache-the-metadata\\n - [dynamic] Render a marker component that calls \\`await connection()\\` inside \\`\\` on the page\\n https://nextjs.org/docs/messages/blocking-prerender-metadata-dynamic#mark-the-route-as-dynamic", + "1293": "Route \"%s\": Next.js encountered runtime data in \\`generateViewport()\\`.\\n\\n\\`cookies()\\`, \\`headers()\\`, \\`params\\`, or \\`searchParams\\` in \\`generateViewport()\\` prevents the page from being prerendered, leading to a slower user experience.\\n\\nWays to fix this:\\n - [static] Use a static viewport export instead of \\`generateViewport()\\`\\n https://nextjs.org/docs/messages/blocking-prerender-viewport-runtime#use-static-viewport\\n - [block] Set \\`export const unstable_instant = false\\` to silence this warning and allow a blocking route\\n https://nextjs.org/docs/messages/blocking-prerender-viewport-runtime#allow-blocking-route", + "1294": "Route \"%s\": Next.js encountered uncached or runtime data in \\`generateMetadata()\\`.\\n\\nThis route's metadata is blocked, but the rest of its content can be prerendered.\\n\\nWays to fix this:\\n - [static] Use a static metadata export instead of \\`generateMetadata()\\`\\n https://nextjs.org/docs/messages/blocking-prerender-metadata-runtime#use-static-metadata\\n - [cache] Cache the metadata with \\`\"use cache\"\\` in \\`generateMetadata()\\`\\n https://nextjs.org/docs/messages/blocking-prerender-metadata-dynamic#cache-the-metadata\\n - [dynamic] Render a marker component that calls \\`await connection()\\` inside \\`\\` on the page\\n https://nextjs.org/docs/messages/blocking-prerender-metadata-dynamic#mark-the-route-as-dynamic", + "1295": "Route \"%s\": Next.js encountered the unstable value %s while prerendering.\\n\\nThis value can change between renders, so it must be either prerendered or computed later.\\n\\nWays to fix this:\\n - [dynamic] Render at request time by adding a dynamic data access (e.g. \\`await connection()\\`) before this call\\n %s#generate-on-every-request\\n - [cache] Prerender and cache the value with \\`\"use cache\"\\`\\n %s%s\\n - [client] Render the value on the client with \\`\"use client\"\\`\\n %s#render-on-the-client%s", + "1296": "Route \"%s\": Next.js encountered runtime data during prerendering.\\n\\n\\`cookies()\\`, \\`headers()\\`, \\`params\\`, or \\`searchParams\\` accessed outside of \\`\\` prevents the route from being prerendered, blocking the page load and leading to a slower user experience.\\n\\nWays to fix this:\\n - [stream] Provide a placeholder with \\`\\` around the data access\\n https://nextjs.org/docs/messages/blocking-prerender-runtime#wrap-in-or-move-into-suspense\\n - [cache] If the runtime data is \\`params\\` and they're known, prerender them with \\`generateStaticParams\\`\\n https://nextjs.org/docs/messages/blocking-prerender-runtime#for-known-params-prerender\\n - [block] Set \\`export const unstable_instant = false\\` to silence this warning and allow a blocking route\\n https://nextjs.org/docs/messages/blocking-prerender-runtime#allow-blocking-route", + "1297": "Route \"%s\": Next.js encountered runtime data during prerendering or a navigation.\\n\\n\\`cookies()\\`, \\`headers()\\`, \\`params\\`, or \\`searchParams\\` accessed outside of \\`\\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\\n\\nWays to fix this:\\n - [stream] Provide a placeholder with \\`\\` around the data access\\n https://nextjs.org/docs/messages/blocking-prerender-runtime#wrap-in-or-move-into-suspense\\n - [cache] If the runtime data is \\`params\\` and they're known, prerender them with \\`generateStaticParams\\`\\n https://nextjs.org/docs/messages/blocking-prerender-runtime#for-known-params-prerender\\n - [block] Set \\`export const unstable_instant = false\\` to silence this warning and allow a blocking route\\n https://nextjs.org/docs/messages/blocking-prerender-runtime#allow-blocking-route", + "1298": "Route \"%s\": Next.js encountered uncached data during prerendering or a navigation.\\n\\n\\`fetch(...)\\` or \\`connection()\\` accessed outside of \\`\\` prevents the route from being prerendered or the navigation from being instant, leading to a slower user experience.\\n\\nWays to fix this:\\n - [cache] Cache the data access with \\`\"use cache\"\\`\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#cache-the-component-or-data\\n - [stream] Provide a placeholder with \\`\\` around the data access\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#wrap-in-or-move-into-suspense\\n - [block] Set \\`export const unstable_instant = false\\` to silence this warning and allow a blocking route\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#allow-blocking-route", + "1299": "Route \"%s\": Next.js encountered uncached or runtime data during prerendering.\\n\\n\\`fetch(...)\\`, \\`cookies()\\`, \\`headers()\\`, \\`params\\`, \\`searchParams\\`, or \\`connection()\\` accessed outside of \\`\\` prevents the route from being prerendered, blocking the page load and leading to a slower user experience.\\n\\nWays to fix this:\\n - [cache] Cache the data access with \\`\"use cache\"\\`\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#cache-the-component-or-data\\n - [stream] Provide a placeholder with \\`\\` around the data access\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#wrap-in-or-move-into-suspense\\n - [cache] If the runtime data is \\`params\\` and they're known, prerender them with \\`generateStaticParams\\`\\n https://nextjs.org/docs/messages/blocking-prerender-runtime#for-known-params-prerender\\n - [block] Set \\`export const unstable_instant = false\\` to silence this warning and allow a blocking route\\n https://nextjs.org/docs/messages/blocking-prerender-dynamic#allow-blocking-route", + "1300": "A render that hasn't started yet cannot be abandoned", + "1301": "Cannot determine late/early stage before starting the render", + "1302": "Attempted to advance to stage %s but the render is limited to %s" } diff --git a/packages/next/package.json b/packages/next/package.json index 95fe24fd85c9..c9d8d556250a 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "16.3.0-canary.39", + "version": "16.3.0-canary.40", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -101,7 +101,7 @@ ] }, "dependencies": { - "@next/env": "16.3.0-canary.39", + "@next/env": "16.3.0-canary.40", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", @@ -165,11 +165,11 @@ "@modelcontextprotocol/sdk": "1.18.1", "@mswjs/interceptors": "0.23.0", "@napi-rs/triples": "1.2.0", - "@next/font": "16.3.0-canary.39", - "@next/polyfill-module": "16.3.0-canary.39", - "@next/polyfill-nomodule": "16.3.0-canary.39", - "@next/react-refresh-utils": "16.3.0-canary.39", - "@next/swc": "16.3.0-canary.39", + "@next/font": "16.3.0-canary.40", + "@next/polyfill-module": "16.3.0-canary.40", + "@next/polyfill-nomodule": "16.3.0-canary.40", + "@next/react-refresh-utils": "16.3.0-canary.40", + "@next/swc": "16.3.0-canary.40", "@opentelemetry/api": "1.6.0", "@playwright/test": "1.58.2", "@rspack/core": "1.6.7", diff --git a/packages/next/src/build/templates/app-page.ts b/packages/next/src/build/templates/app-page.ts index 4689e1247d07..d123b984c998 100644 --- a/packages/next/src/build/templates/app-page.ts +++ b/packages/next/src/build/templates/app-page.ts @@ -899,6 +899,7 @@ export async function handler( cachedNavigations: Boolean( nextConfig.experimental.cachedNavigations ), + appShells: nextConfig.experimental.appShells, clientTraceMetadata: nextConfig.experimental.clientTraceMetadata || ([] as any), clientParamParsingOrigins: diff --git a/packages/next/src/build/templates/edge-ssr-app.ts b/packages/next/src/build/templates/edge-ssr-app.ts index 6b521e89126d..99a6f985549f 100644 --- a/packages/next/src/build/templates/edge-ssr-app.ts +++ b/packages/next/src/build/templates/edge-ssr-app.ts @@ -171,6 +171,7 @@ async function requestHandler( authInterrupts: Boolean(nextConfig.experimental.authInterrupts), useCacheTimeout: nextConfig.experimental.useCacheTimeout, cachedNavigations: Boolean(nextConfig.experimental.cachedNavigations), + appShells: nextConfig.experimental.appShells, clientTraceMetadata: nextConfig.experimental.clientTraceMetadata || ([] as any), clientParamParsingOrigins: diff --git a/packages/next/src/export/index.ts b/packages/next/src/export/index.ts index b8986944043a..6d6997d2af1f 100644 --- a/packages/next/src/export/index.ts +++ b/packages/next/src/export/index.ts @@ -518,6 +518,7 @@ async function exportAppImpl( authInterrupts: !!nextConfig.experimental.authInterrupts, useCacheTimeout: nextConfig.experimental.useCacheTimeout, cachedNavigations: nextConfig.experimental.cachedNavigations ?? false, + appShells: nextConfig.experimental.appShells, maxPostponedStateSizeBytes: parseMaxPostponedStateSize( nextConfig.experimental.maxPostponedStateSize ), diff --git a/packages/next/src/lib/metadata/metadata.tsx b/packages/next/src/lib/metadata/metadata.tsx index 48c0bdca81e6..bb6fae207cc7 100644 --- a/packages/next/src/lib/metadata/metadata.tsx +++ b/packages/next/src/lib/metadata/metadata.tsx @@ -21,7 +21,6 @@ import { workUnitAsyncStorage, getStagedRenderingController, } from '../../server/app-render/work-unit-async-storage.external' -import { RenderStage } from '../../server/app-render/staged-rendering' import { MetadataBoundary, @@ -31,6 +30,7 @@ import { import { getOrigin } from './generate/utils' import { IconMark } from './generate/icon-mark' +import { FIRST_LATE_RENDER_STAGE } from '../../server/app-render/staged-rendering' // Use a promise to share the status of the metadata resolving, // returning two components `MetadataTree` and `MetadataOutlet` @@ -72,14 +72,14 @@ export function createMetadataComponents({ async function Viewport() { // Gate metadata to the correct render stage. If the page is not - // runtime-prefetchable, defer until the Static stage so that + // runtime-prefetchable, defer until the ShellStatic stage so that // prefetchable segments get a head start. if (!isRuntimePrefetchable) { const workUnitStore = workUnitAsyncStorage.getStore() if (workUnitStore) { const stagedRendering = getStagedRenderingController(workUnitStore) if (stagedRendering) { - await stagedRendering.waitForStage(RenderStage.Static) + await stagedRendering.waitForStage(FIRST_LATE_RENDER_STAGE) } } } @@ -123,14 +123,14 @@ export function createMetadataComponents({ async function Metadata() { // Gate metadata to the correct render stage. If the page is not - // runtime-prefetchable, defer until the Static stage so that + // runtime-prefetchable, defer until the ShellStatic stage so that // prefetchable segments get a head start. if (!isRuntimePrefetchable) { const workUnitStore = workUnitAsyncStorage.getStore() if (workUnitStore) { const stagedRendering = getStagedRenderingController(workUnitStore) if (stagedRendering) { - await stagedRendering.waitForStage(RenderStage.Static) + await stagedRendering.waitForStage(FIRST_LATE_RENDER_STAGE) } } } diff --git a/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts b/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts index 0f17e4026f3a..c35801231924 100644 --- a/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts +++ b/packages/next/src/next-devtools/dev-overlay/components/instant/instant-guidance-data.ts @@ -50,6 +50,11 @@ export type FixCard = { /** Docs URL the card links to, or `null` for no link. */ link: string | null snippets: Snippet[] + /** + * AI-agent prompt copied when the user presses the "Copy prompt" button on + * the card. Phrased as an instruction the agent can act on directly. + */ + prompt?: string } export type SnippetPart = { @@ -73,18 +78,20 @@ const runtimeCards: FixCard[] = [ id: 'wrap-in-or-move-into-suspense', title: 'Wrap in or move into Suspense', group: 'stream', - link: 'https://nextjs.org/docs/messages/blocking-route#wrap-in-or-move-into-suspense', + link: 'https://nextjs.org/docs/messages/blocking-prerender-runtime#wrap-in-or-move-into-suspense', snippets: [ { text: '', highlight: true }, { text: ' ' }, { text: '', highlight: true }, ], + prompt: + 'Wrap the component that reads cookies(), headers(), params, or searchParams in . The fallback prop must render synchronous, deterministic JSX (no fetch, no awaiting, no Math.random or Date.now) that approximates the final layout (skeleton, spinner, or stable placeholder text). Import Suspense from "react". Do not change the data access call. Place the Suspense boundary as close to the access as possible so the cached content above remains in the static shell. If the access is deep in a tree and used for a small piece of UI, prefer to push the access down to the leaf component that needs it instead of awaiting it at the top and forwarding the value.', }, { - id: 'prerender-known-params', + id: 'for-known-params-prerender', title: 'For known params, prerender', group: 'cache', - link: 'https://nextjs.org/docs/messages/blocking-route#prerender-known-params', + link: 'https://nextjs.org/docs/messages/blocking-prerender-runtime#for-known-params-prerender', snippets: [ { text: 'function generateStaticParams() {', @@ -103,16 +110,20 @@ const runtimeCards: FixCard[] = [ }, { text: '}' }, ], + prompt: + 'Add a generateStaticParams() export to the dynamic segment. Return an array of param objects whose keys match the segment\'s [param] names. Each entry is prerendered into static HTML at build time. With Cache Components, requests for params not in the list are served a fallback shell and the route is upgraded in the background. Return a subset of known params for common routes (popular categories, top locales, recent slugs); rare or open-ended params will fall back at runtime. Do not introduce new imports beyond Next.js types. If you can\'t return at least one known param at build time, use "Wrap in or move into Suspense" instead.', }, { id: 'allow-blocking-route', title: 'Allow blocking route', group: 'block', - link: 'https://nextjs.org/docs/messages/blocking-route#allow-blocking-route', + link: 'https://nextjs.org/docs/messages/blocking-prerender-runtime#allow-blocking-route', snippets: [ { text: '// page.tsx or layout.tsx' }, { text: 'export const instant = false', highlight: true }, ], + prompt: + 'Add "export const instant = false" as a top-level export in the page or layout file. This silences the warning for this segment. Confirm with the user that the route is intentionally request-time before applying this change: the export exempts the segment from instant-navigation validation, and the route renders on every request, so navigations to it block until the render completes. If the user wants to keep the navigation instant, choose "Wrap in or move into Suspense" or "Prerender known params" instead.', }, ] @@ -121,33 +132,39 @@ const dynamicCards: FixCard[] = [ id: 'cache-the-component-or-data', title: 'Cache the component or data', group: 'cache', - link: 'https://nextjs.org/docs/messages/blocking-route#cache-the-component-or-data', + link: 'https://nextjs.org/docs/messages/blocking-prerender-dynamic#cache-the-component-or-data', snippets: [ { text: 'async function Posts() {' }, { text: ' "use cache"', highlight: true }, { text: ' return ' }, ], + prompt: + 'Convert the highlighted data access into a cached function. Put "use cache" as the first statement of the function body. If the value depends on input that changes between calls, accept the input as a function argument so it becomes part of the cache key. Optionally call cacheTag(tag) to allow invalidation via revalidateTag(tag), and cacheLife(profile) to set automatic expiration. Do not move the call site. Do not introduce new imports beyond "next/cache".', }, { id: 'wrap-in-or-move-into-suspense', title: 'Wrap in or move into Suspense', group: 'stream', - link: 'https://nextjs.org/docs/messages/blocking-route#wrap-in-or-move-into-suspense', + link: 'https://nextjs.org/docs/messages/blocking-prerender-dynamic#wrap-in-or-move-into-suspense', snippets: [ { text: '', highlight: true }, { text: ' ' }, { text: '', highlight: true }, ], + prompt: + 'Wrap the component that performs the failing data access in . The fallback prop must render synchronous, deterministic JSX (no fetch, no awaiting, no Math.random or Date.now) that approximates the final layout (skeleton, spinner, or stable placeholder text). Import Suspense from "react". Do not change the data fetching logic. If the surrounding parent component already has cached content, place the Suspense boundary as close to the data access as possible so the cached content remains in the static shell.', }, { id: 'allow-blocking-route', title: 'Allow blocking route', group: 'block', - link: 'https://nextjs.org/docs/messages/blocking-route#allow-blocking-route', + link: 'https://nextjs.org/docs/messages/blocking-prerender-dynamic#allow-blocking-route', snippets: [ { text: '// page.tsx or layout.tsx' }, { text: 'export const instant = false', highlight: true }, ], + prompt: + 'Add "export const instant = false" as a top-level export in the page or layout file. This silences the warning for this segment. Confirm with the user that the route is intentionally request-time before applying this change: the export exempts the segment from instant-navigation validation, and the route renders on every request, so navigations to it block until the render completes. If the user wants to keep the navigation instant, choose "Cache the component or data" or "Wrap in or move into Suspense" instead.', }, ] @@ -158,7 +175,7 @@ const unrenderedSegmentCards: FixCard[] = [ id: 'render-the-dropped-segment', title: 'Render the dropped segment', group: 'render', - link: 'https://nextjs.org/docs/messages/unrendered-instant-segment#render-the-dropped-segment', + link: 'https://nextjs.org/docs/messages/instant-unrendered-segment#render-the-dropped-segment', snippets: [ { text: 'function Layout({ children }) {', @@ -178,17 +195,21 @@ const unrenderedSegmentCards: FixCard[] = [ }, { text: '}' }, ], + prompt: + 'Ensure the layout renders {children} so the dropped segment is included in the render tree. If the layout conditionally omits {children} (e.g. showing a login page instead), restructure so both branches render {children} and use a Suspense boundary or conditional content inside the child segment instead. If the segment is a parallel route slot, ensure the layout renders the slot prop.', }, { id: 'skip-validation-on-the-segment', title: 'Skip validation on the segment', group: 'ignore', - link: 'https://nextjs.org/docs/messages/unrendered-instant-segment#skip-validation-on-the-segment', + link: 'https://nextjs.org/docs/messages/instant-unrendered-segment#skip-validation-on-the-segment', snippets: [ { text: '// page.tsx or layout.tsx' }, { text: '' }, { text: 'export const instant = false', highlight: true }, ], + prompt: + 'Add "export const unstable_instant = false" as a top-level export in the dropped segment\'s page or layout file. This silences the warning for the dropped segment and tells Next.js the segment does not need instant-navigation validation. Confirm with the user that skipping validation is intentional before applying this change.', }, ] @@ -199,22 +220,26 @@ const metadataRuntimeCards: FixCard[] = [ id: 'use-static-metadata', title: 'Use static metadata', group: 'static', - link: 'https://nextjs.org/docs/messages/next-prerender-dynamic-metadata#use-static-metadata', + link: 'https://nextjs.org/docs/messages/blocking-prerender-metadata-runtime#use-static-metadata', snippets: [ { text: 'export const metadata = {', highlight: true }, { text: ' title: "My Page"' }, { text: '}' }, ], + prompt: + 'Replace the generateMetadata() function with a static metadata export. Convert all dynamic values to static strings. If the metadata depends on params, use generateStaticParams instead to prerender each variant. Do not introduce new imports.', }, { id: 'render-page-at-request-time', title: 'Mark the route as dynamic', group: 'dynamic', - link: 'https://nextjs.org/docs/messages/next-prerender-dynamic-metadata#render-page-at-request-time', + link: 'https://nextjs.org/docs/messages/blocking-prerender-metadata-runtime#mark-the-route-as-dynamic', snippets: [ { text: '// page.tsx or layout.tsx' }, { text: 'await connection()', highlight: true }, ], + prompt: + 'Add "await connection()" from "next/server" inside a component rendered by the page, wrapped in . The component can render null. This creates a dynamic hole inside Suspense so the rest of the page can still prerender, while signalling to Next.js that the dynamic metadata is intentional. Use this fix when the page would otherwise have no dynamic content other than the metadata.', }, ] @@ -223,22 +248,26 @@ const metadataDynamicCards: FixCard[] = [ id: 'cache-the-metadata', title: 'Cache the metadata', group: 'cache', - link: 'https://nextjs.org/docs/messages/next-prerender-dynamic-metadata#cache-the-metadata', + link: 'https://nextjs.org/docs/messages/blocking-prerender-metadata-dynamic#cache-the-metadata', snippets: [ { text: 'async function generateMetadata() {' }, { text: ' "use cache"', highlight: true }, { text: ' return await cms.getMeta(…)' }, ], + prompt: + 'Add "use cache" as the first statement inside generateMetadata(). This caches the metadata so it can be included in the prerender. Optionally call cacheTag(tag) so the entry can be invalidated on-demand from a Server Action via updateTag(tag), or from a Route Handler via revalidateTag(tag, "max") for stale-while-revalidate semantics. Optionally call cacheLife(profile) to control how long the cache lives before background revalidation or full expiration. Do not introduce new imports beyond "next/cache".', }, { id: 'render-page-at-request-time', title: 'Mark the route as dynamic', group: 'dynamic', - link: 'https://nextjs.org/docs/messages/next-prerender-dynamic-metadata#render-page-at-request-time', + link: 'https://nextjs.org/docs/messages/blocking-prerender-metadata-dynamic#mark-the-route-as-dynamic', snippets: [ { text: '// page.tsx or layout.tsx' }, { text: 'await connection()', highlight: true }, ], + prompt: + 'Add "await connection()" from "next/server" inside a component rendered by the page, wrapped in . The component can render null. This creates a dynamic hole inside Suspense so the rest of the page can still prerender, while signalling to Next.js that the dynamic metadata is intentional. Use this fix when the page would otherwise have no dynamic content other than the metadata.', }, ] @@ -249,22 +278,26 @@ const viewportRuntimeCards: FixCard[] = [ id: 'use-static-viewport', title: 'Use static viewport', group: 'static', - link: 'https://nextjs.org/docs/messages/next-prerender-dynamic-viewport#use-static-viewport', + link: 'https://nextjs.org/docs/messages/blocking-prerender-viewport-runtime#use-static-viewport', snippets: [ { text: 'export const viewport = {', highlight: true }, { text: ' themeColor: "#000"' }, { text: '}' }, ], + prompt: + 'Replace the generateViewport() function with a static viewport export. Convert all dynamic values to static ones. Do not introduce new imports.', }, { id: 'allow-blocking-route', title: 'Allow blocking route', group: 'block', - link: 'https://nextjs.org/docs/messages/next-prerender-dynamic-viewport#allow-blocking-route', + link: 'https://nextjs.org/docs/messages/blocking-prerender-viewport-runtime#allow-blocking-route', snippets: [ { text: '// page.tsx or layout.tsx' }, { text: 'export const instant = false', highlight: true }, ], + prompt: + 'Add "export const unstable_instant = false" as a top-level export in the page or layout file. This silences the warning for this segment. Confirm with the user that the route is intentionally fully dynamic before applying this change: the export exempts the segment from instant-navigation validation, and the route renders on every request. If the user wants to keep the navigation instant, choose "Use static viewport" instead.', }, ] @@ -273,22 +306,26 @@ const viewportDynamicCards: FixCard[] = [ id: 'cache-viewport-data', title: 'Cache the viewport data', group: 'cache', - link: 'https://nextjs.org/docs/messages/next-prerender-dynamic-viewport#cache-viewport-data', + link: 'https://nextjs.org/docs/messages/blocking-prerender-viewport-dynamic#cache-the-viewport-data', snippets: [ { text: 'async function generateViewport() {' }, { text: ' "use cache"', highlight: true }, { text: ' return await db.getViewport(…)' }, ], + prompt: + 'Add "use cache" as the first statement inside generateViewport(). This caches the viewport so Next.js can include it in the prerender. Optionally call cacheLife(profile) to set automatic expiration. Do not introduce new imports beyond "next/cache".', }, { id: 'allow-blocking-route', title: 'Allow blocking route', group: 'block', - link: 'https://nextjs.org/docs/messages/next-prerender-dynamic-viewport#allow-blocking-route', + link: 'https://nextjs.org/docs/messages/blocking-prerender-viewport-dynamic#allow-blocking-route', snippets: [ { text: '// page.tsx or layout.tsx' }, { text: 'export const instant = false', highlight: true }, ], + prompt: + 'Add "export const unstable_instant = false" as a top-level export in the page or layout file. This silences the warning for this segment. Confirm with the user that the route is intentionally fully dynamic before applying this change: the export exempts the segment from instant-navigation validation, and the route renders on every request. If the user wants to keep the navigation instant, choose "Cache the viewport data" instead.', }, ] @@ -299,34 +336,40 @@ const syncMathCards: FixCard[] = [ id: 'render-at-request-time', title: 'Generate on every request', group: 'dynamic', - link: 'https://nextjs.org/docs/messages/next-prerender-random#render-at-request-time', + link: 'https://nextjs.org/docs/messages/blocking-prerender-random#generate-on-every-request', snippets: [ { text: 'await connection()', highlight: true }, { text: 'const id = Math.random()' }, { text: 'return ' }, ], + prompt: + 'Add "await connection()" from "next/server" immediately before the Math.random() call. This marks the component as request-time, so Next.js excludes it from the prerendered HTML and streams it in from the nearest boundary on each request. Do not change the call site of Math.random() itself. Only change the call site once you\'ve confirmed with the user that a fresh value on every request is the intent.', }, { id: 'cache-the-random-value', title: 'Cache the random value', group: 'cache', - link: 'https://nextjs.org/docs/messages/next-prerender-random#cache-the-random-value', + link: 'https://nextjs.org/docs/messages/blocking-prerender-random#cache-the-random-value', snippets: [ { text: 'function RandomId() {' }, { text: ' "use cache"', highlight: true }, { text: ' return String(Math.random())' }, ], + prompt: + 'Move the Math.random() call into its own function or component and add "use cache" as the first statement of the body. Optionally call cacheLife(profile) to control how long the same random value is reused before regeneration. Do not introduce new imports beyond "next/cache".', }, { id: 'render-on-the-client', title: 'Render on the client', group: 'client', - link: 'https://nextjs.org/docs/messages/next-prerender-random#render-on-the-client', + link: 'https://nextjs.org/docs/messages/blocking-prerender-random#render-on-the-client', snippets: [ { text: '"use client"', highlight: true }, { text: '// runs in the browser' }, { text: 'const id = Math.random()' }, ], + prompt: + 'Move the component that calls Math.random() into a Client Component by adding "use client" at the top of the file. The browser produces a fresh value on each visit. If the value needs to be hydration-stable, compute it inside a useEffect or event handler instead of inline during render.', }, ] @@ -335,45 +378,53 @@ const syncDateCards: FixCard[] = [ id: 'render-at-request-time', title: 'Generate on every request', group: 'dynamic', - link: 'https://nextjs.org/docs/messages/next-prerender-current-time#render-at-request-time', + link: 'https://nextjs.org/docs/messages/blocking-prerender-current-time#generate-on-every-request', snippets: [ { text: 'await connection()', highlight: true }, { text: 'const t = Date.now()' }, { text: 'return ' }, ], + prompt: + 'Add "await connection()" from "next/server" immediately before the Date.now() call. This marks the component as request-time, so Next.js excludes it from the prerendered HTML and streams it in from the nearest boundary on each request. Do not change the call site of Date.now() itself. Only change the call site once you\'ve confirmed with the user that a fresh value on every request is the intent.', }, { id: 'cache-the-timestamp', title: 'Cache the timestamp', group: 'cache', - link: 'https://nextjs.org/docs/messages/next-prerender-current-time#cache-the-timestamp', + link: 'https://nextjs.org/docs/messages/blocking-prerender-current-time#cache-the-timestamp', snippets: [ { text: 'function Timestamp() {' }, { text: ' "use cache"', highlight: true }, { text: ' return ' }, ], + prompt: + 'Move the Date.now() call into its own function and add "use cache" as the first statement. Optionally call cacheLife(profile) to control how often the timestamp is regenerated. Do not introduce new imports beyond "next/cache".', }, { id: 'render-on-the-client', title: 'Render on the client', group: 'client', - link: 'https://nextjs.org/docs/messages/next-prerender-current-time#render-on-the-client', + link: 'https://nextjs.org/docs/messages/blocking-prerender-current-time#render-on-the-client', snippets: [ { text: '"use client"', highlight: true }, { text: '// runs in the browser' }, { text: 'const t = Date.now()' }, ], + prompt: + 'Move the component that calls Date.now() into a Client Component by adding "use client" at the top of the file. If the value needs to be hydration-stable, compute it inside useEffect instead of inline during render.', }, { id: 'measure-elapsed-time', title: 'For telemetry, use a timing API', group: 'measure', - link: 'https://nextjs.org/docs/messages/next-prerender-current-time#measure-elapsed-time', + link: 'https://nextjs.org/docs/messages/blocking-prerender-current-time#for-telemetry-use-a-timing-api', snippets: [ { text: 'const start = performance.now()', highlight: true }, { text: 'doWork()' }, { text: 'const ms = performance.now() - start' }, ], + prompt: + 'Replace Date.now() with performance.now() if the value is used for elapsed-time measurement, instrumentation, or telemetry. performance.now() returns a high-resolution monotonic timestamp and does not interfere with prerendering. Do not change the call if the value is rendered into the UI.', }, ] @@ -382,34 +433,40 @@ const syncCryptoCards: FixCard[] = [ id: 'render-at-request-time', title: 'Generate on every request', group: 'dynamic', - link: 'https://nextjs.org/docs/messages/next-prerender-crypto#render-at-request-time', + link: 'https://nextjs.org/docs/messages/blocking-prerender-crypto#generate-on-every-request', snippets: [ { text: 'await connection()', highlight: true }, { text: 'const id = crypto.randomUUID()' }, { text: 'return ' }, ], + prompt: + 'Add "await connection()" from "next/server" immediately before the crypto call. This marks the component as request-time, so Next.js excludes it from the prerendered HTML and streams it in from the nearest boundary on each request. Do not change the crypto call itself. Only change the call site once you\'ve confirmed with the user that a fresh value on every request is the intent.', }, { id: 'cache-the-generated-value', title: 'Cache the generated value', group: 'cache', - link: 'https://nextjs.org/docs/messages/next-prerender-crypto#cache-the-generated-value', + link: 'https://nextjs.org/docs/messages/blocking-prerender-crypto#cache-the-generated-value', snippets: [ { text: 'function TokenId() {' }, { text: ' "use cache"', highlight: true }, { text: ' return crypto.randomUUID()' }, ], + prompt: + 'Move the crypto call into its own function and add "use cache" as the first statement. Useful when the same generated value is reused as a key for another cached operation (talking to a database, signing a payload). Do not introduce new imports beyond "next/cache".', }, { id: 'render-on-the-client', title: 'Render on the client', group: 'client', - link: 'https://nextjs.org/docs/messages/next-prerender-crypto#render-on-the-client', + link: 'https://nextjs.org/docs/messages/blocking-prerender-crypto#render-on-the-client', snippets: [ { text: '"use client"', highlight: true }, { text: '// runs in the browser' }, { text: 'const id = crypto.randomUUID()' }, ], + prompt: + 'Move the component that calls the crypto API into a Client Component by adding "use client" at the top of the file. The browser produces the value, so the server never has to. If the value needs to be hydration-stable, compute it inside useEffect instead of inline during render.', }, ] @@ -420,34 +477,40 @@ const syncClientDateCards: FixCard[] = [ id: 'wrap-in-or-move-into-suspense', title: 'Wrap in or move into Suspense', group: 'stream', - link: 'https://nextjs.org/docs/messages/next-prerender-current-time-client#wrap-in-or-move-into-suspense', + link: 'https://nextjs.org/docs/messages/blocking-prerender-current-time-client#wrap-in-or-move-into-suspense', snippets: [ { text: '', highlight: true }, { text: ' ' }, { text: '', highlight: true }, ], + prompt: + 'Wrap the Client Component that calls Date.now() in in its parent. The fallback prop must render synchronous, deterministic JSX (no Date.now or Math.random) that approximates the final layout. Import Suspense from "react". Do not change the Date.now() call.', }, { id: 'move-into-effect-or-event-handler', title: 'Move into effect or event handler', group: 'defer', - link: 'https://nextjs.org/docs/messages/next-prerender-current-time-client#move-into-effect-or-event-handler', + link: 'https://nextjs.org/docs/messages/blocking-prerender-current-time-client#move-into-effect-or-event-handler', snippets: [ { text: '