Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 34 additions & 7 deletions crates/next-api/src/pages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,27 +233,35 @@ impl PagesProject {
}

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

#[turbo_tasks::function]
async fn to_endpoint(
self: Vc<Self>,
item: Vc<PagesStructureItem>,
ty: PageEndpointType,
) -> Result<Vc<Box<dyn Endpoint>>> {
Ok(Vc::upcast(self.to_page_endpoint(item, ty)))
}

#[turbo_tasks::function]
Expand All @@ -264,9 +272,16 @@ impl PagesProject {
))
}

/// The `/_app` endpoint. Its client chunk group is generated first and seeds the availability
/// information of every other page, so it must never depend on an individual page.
#[turbo_tasks::function]
async fn app_page_endpoint(self: Vc<Self>) -> Result<Vc<PageEndpoint>> {
Ok(self.to_page_endpoint(*self.pages_structure().await?.app, PageEndpointType::Html))
}

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

#[turbo_tasks::function]
Expand Down Expand Up @@ -797,12 +812,24 @@ impl PageEndpoint {
.iter()
.map(|m| ResolvedVc::upcast(*m))
.collect();
// Like App Router layouts, `/_app` is always loaded before the page. Chunk it first so
// the page's chunks don't include modules that the browser already downloaded with
// `/_app`.
let availability_info = if this.pathname == "/_app" {
AvailabilityInfo::root()
} else {
this.pages_project
.app_page_endpoint()
.client_chunk_group()
.await?
.availability_info
};
let client_chunk_group = client_chunking_context.evaluated_chunk_group(
AssetIdent::from_path(this.page.await?.base_path.clone()).into_vc(),
ChunkGroup::Entry(evaluatable_assets),
module_graph,
OutputAssets::empty(),
AvailabilityInfo::root(),
availability_info,
);

Ok(client_chunk_group)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ impl ReactServerComponentValidator {
"cacheTag",
"unstable_cacheTag",
"unstable_navigation",
"unstable_prefetch",
// "unstable_noStore" // no-op in client, but allowed for legacy reasons
],
),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { unstable_prefetch } from 'next/cache'

export async function test() {
await unstable_prefetch()
return null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { unstable_prefetch } from 'next/cache';
export async function test() {
await unstable_prefetch();
return null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
x You're importing a module that depends on "unstable_prefetch" into a React Client Component module. This API is only available in Server Components but one of its parents is marked with "use
| client", so this module is also a Client Component.
| Learn more: https://nextjs.org/docs/app/building-your-application/rendering
|
|
,-[input.js:1:1]
1 | import { unstable_prefetch } from 'next/cache'
: ^^^^^^^^^^^^^^^^^
`----
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { unstable_prefetch } from 'next/cache'

export async function test() {
await unstable_prefetch()
return null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { unstable_prefetch } from 'next/cache';
export async function test() {
await unstable_prefetch();
return null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
x You're importing a module that depends on "unstable_prefetch". This API is only available in Server Components in the App Router, but you are using it in the Pages Router.
| Learn more: https://nextjs.org/docs/app/building-your-application/rendering/server-components
|
|
,-[input.js:1:1]
1 | import { unstable_prefetch } from 'next/cache'
: ^^^^^^^^^^^^^^^^^
`----
2 changes: 1 addition & 1 deletion docs/01-app/02-guides/migrating/app-router-migration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ To upgrade your links to Next.js 13, you can use the [`new-link` codemod](/docs/

The behavior of [`next/script`](/docs/app/api-reference/components/script) has been updated to support both `pages` and `app`, but some changes need to be made to ensure a smooth migration:

- Move any `beforeInteractive` scripts you previously included in `_document.js` to the root layout file (`app/layout.tsx`).
- Move any `beforeInteractive` scripts you previously included in `_document.js` to a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), such as `app/layout.tsx` or `app/[locale]/layout.tsx`.
- The experimental `worker` strategy does not yet work in `app` and scripts denoted with this strategy will either have to be removed or modified to use a different strategy (e.g. `lazyOnload`).
- `onLoad`, `onReady`, and `onError` handlers will not work in Server Components so make sure to move them to a [Client Component](/docs/app/getting-started/server-and-client-components) or remove them altogether.

Expand Down
8 changes: 7 additions & 1 deletion docs/01-app/03-api-reference/02-components/script.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Scripts denoted with this strategy are preloaded and fetched before any first-pa

<AppOnly>

`beforeInteractive` scripts must be placed inside the root layout (`app/layout.tsx`) and are designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).
Scripts with the `beforeInteractive` strategy must be placed inside a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), such as `app/layout.tsx` or `app/[locale]/layout.tsx`, and are designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).

</AppOnly>

Expand Down Expand Up @@ -155,6 +155,12 @@ export default function Document() {

> **Good to know**: Scripts with `beforeInteractive` will always be injected inside the `head` of the HTML document regardless of where it's placed in the component.

<AppOnly>

> **Good to know**: These scripts run once per document load. A client-side navigation does not run them again, including one that only changes a root param, such as `/en` to `/fi`, since the root layout stays the same.

</AppOnly>

Some examples of scripts that should be fetched as soon as possible with `beforeInteractive` include:

- Bot detectors
Expand Down
2 changes: 1 addition & 1 deletion docs/01-app/03-api-reference/04-functions/cacheLife.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ A short cache lifetime changes where the cached content can be delivered from:

- **`revalidate` of `0`, or `expire` under 5 minutes**: excluded from prerenders, becoming a "dynamic hole" resolved at request time.
- **`stale` under 30 seconds**: excluded from prerenders, because a prefetch would expire before the user could click.
- **`stale` from 30 seconds up to 5 minutes**: included in prerenders, but excluded from the route's [App Shell](/docs/app/glossary#app-shell).
- **`stale` of at least 30 seconds but under 5 minutes**: included in prerenders, but excluded from the route's [App Shell](/docs/app/glossary#app-shell).

Of the presets, only `seconds` falls under any of these thresholds: its `expire` of 1 minute excludes it from prerenders.

Expand Down
32 changes: 0 additions & 32 deletions docs/01-app/03-api-reference/07-adapters/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,3 @@ description: Build deployment adapters for Next.js platforms and infrastructure.
---

Use this section to build and validate deployment adapters that integrate with the Next.js build and runtime model.

<AppOnly>

- [Configuration](/docs/app/api-reference/adapters/configuration)
- [Creating an Adapter](/docs/app/api-reference/adapters/creating-an-adapter)
- [API Reference](/docs/app/api-reference/adapters/api-reference)
- [Testing Adapters](/docs/app/api-reference/adapters/testing-adapters)
- [Routing with `@next/routing`](/docs/app/api-reference/adapters/routing-with-next-routing)
- [Implementing PPR in an Adapter](/docs/app/api-reference/adapters/implementing-ppr-in-an-adapter)
- [Runtime Integration](/docs/app/api-reference/adapters/runtime-integration)
- [Invoking Entrypoints](/docs/app/api-reference/adapters/invoking-entrypoints)
- [Output Types](/docs/app/api-reference/adapters/output-types)
- [Routing Information](/docs/app/api-reference/adapters/routing-information)
- [Use Cases](/docs/app/api-reference/adapters/use-cases)
- [Supporting Immutable Static Assets](/docs/app/api-reference/adapters/immutable-static-assets)

</AppOnly>

<PagesOnly>

- [Configuration](/docs/pages/api-reference/adapters/configuration)
- [Creating an Adapter](/docs/pages/api-reference/adapters/creating-an-adapter)
- [API Reference](/docs/pages/api-reference/adapters/api-reference)
- [Testing Adapters](/docs/pages/api-reference/adapters/testing-adapters)
- [Routing with `@next/routing`](/docs/pages/api-reference/adapters/routing-with-next-routing)
- [Runtime Integration](/docs/pages/api-reference/adapters/runtime-integration)
- [Invoking Entrypoints](/docs/pages/api-reference/adapters/invoking-entrypoints)
- [Output Types](/docs/pages/api-reference/adapters/output-types)
- [Routing Information](/docs/pages/api-reference/adapters/routing-information)
- [Use Cases](/docs/pages/api-reference/adapters/use-cases)

</PagesOnly>
6 changes: 3 additions & 3 deletions errors/no-before-interactive-script-outside-document.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
title: No Before Interactive Script Outside Document
---

> Prevent usage of `next/script`'s `beforeInteractive` strategy outside of `app/layout.jsx` or `pages/_document.js`.
> Prevent usage of `next/script`'s `beforeInteractive` strategy outside of a root layout or `pages/_document.js`.

## Why This Error Occurred

You cannot use the `next/script` component with the `beforeInteractive` strategy outside `app/layout.jsx` or `pages/_document.js`. That's because `beforeInteractive` strategy only works inside **`app/layout.jsx`** or **`pages/_document.js`** and is designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).
You cannot use the `next/script` component with the `beforeInteractive` strategy outside a root layout or `pages/_document.js`. That's because `beforeInteractive` strategy only works inside a **root layout** or **`pages/_document.js`** and is designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).

## Possible Ways to Fix It

### App Router

If you want a global script, and you are using the App Router, move the script inside `app/layout.jsx`.
If you want a global script, and you are using the App Router, move the script inside a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), any layout without a `layout.js` above it.

```jsx filename="app/layout.jsx"
import Script from 'next/script'
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
"registry": "https://registry.npmjs.org/"
}
},
"version": "16.3.1-canary.26"
"version": "16.4.0-canary.0"
}
2 changes: 1 addition & 1 deletion packages/create-next-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-next-app",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"keywords": [
"react",
"next",
Expand Down
2 changes: 1 addition & 1 deletion packages/devlow-bench/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vercel/devlow-bench",
"private": true,
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"description": "Benchmarking tool for the developer workflow",
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-config-next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-config-next",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"description": "ESLint configuration used by Next.js.",
"license": "MIT",
"repository": {
Expand All @@ -12,7 +12,7 @@
"dist"
],
"dependencies": {
"@next/eslint-plugin-next": "16.3.1-canary.26",
"@next/eslint-plugin-next": "16.4.0-canary.0",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.32.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-internal/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@next/eslint-plugin-internal",
"private": true,
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"description": "ESLint plugin for working on Next.js.",
"exports": {
".": "./src/eslint-plugin-internal.js"
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/eslint-plugin-next",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"description": "ESLint plugin for Next.js.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/font/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@next/font",
"private": true,
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/font"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-bundle-analyzer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/bundle-analyzer",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"main": "index.js",
"types": "index.d.ts",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-codemod/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/codemod",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-env/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/env",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"keywords": [
"react",
"next",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-mdx/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"main": "index.js",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-playwright/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/playwright",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-playwright"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-storybook/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-storybook",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-storybook"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-polyfill-module/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-module",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"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",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-polyfill-nomodule/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-nomodule",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"description": "A polyfill for non-dead, nomodule browsers.",
"main": "dist/polyfill-nomodule.js",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-routing/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/routing",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"keywords": [
"react",
"next",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-rspack/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next-rspack",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-rspack"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-swc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/swc",
"version": "16.3.1-canary.26",
"version": "16.4.0-canary.0",
"private": true,
"files": [
"native/"
Expand Down
1 change: 1 addition & 0 deletions packages/next/cache.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,4 @@ export const unstable_cacheLife: typeof cacheLife
export const unstable_cacheTag: typeof cacheTag

export { unstable_navigation } from 'next/dist/server/request/cache-stages'
export { unstable_prefetch } from 'next/dist/server/request/cache-stages'
Loading
Loading