Skip to content

Commit

Permalink
Merge branch 'canary' into FormData
Browse files Browse the repository at this point in the history
  • Loading branch information
vinaykulk621 authored Jul 24, 2023
2 parents 1dc26b9 + a18e2ec commit 579710b
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 100 deletions.
2 changes: 0 additions & 2 deletions docs/01-getting-started/01-installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ Next.js now ships with TypeScript, ESLint, and Tailwind CSS configuration by def

After the prompts, `create-next-app` will create a folder with your project name and install the required dependencies.

> **Good to know**: While you can use the [Pages Router](/docs/pages) in your new project. We recommend starting new applications with the App Router to leverage React's latest features.
## Manual Installation

To manually create a new Next.js app, install the required packages:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ Parallel Routing can be used to render modals.
height="687"
/>

The `@authModal` slot renders a`<Modal>` component that can be shown by navigating to a matching route, for example `/login`.
The `@authModal` slot renders a `<Modal>` component that can be shown by navigating to a matching route, for example `/login`.

```tsx filename="app/layout.tsx" switcher
export default async function Layout(props: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,9 @@ import { NextResponse } from 'next/server'

export async function POST(request: Request) {
const formData = await request.formData()
return NextResponse.json({ formData })
const name = formData.get('name')
const email = formData.get('email')
return NextResponse.json({ name, email })
}
```

Expand All @@ -562,10 +564,14 @@ import { NextResponse } from 'next/server'

export async function POST(request) {
const formData = await request.formData()
return NextResponse.json({ formData })
const name = formData.get('name')
const email = formData.get('email')
return NextResponse.json({ name, email })
}
```

Since `formData` data are all strings, you may want to use [`zod-form-data`](https://www.npmjs.com/zod-form-data) to validate the request and retrieve data in the format you prefer (e.g. `number`).

### CORS

You can set CORS headers on a `Response` using the standard Web API methods:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ When a Server Action is invoked, the UI is updated immediately to reflect the ex
```jsx filename="app/thread.js"
'use client'

import { experimental_useOptimistic as useOptimistic } from 'react'
import { experimental_useOptimistic as useOptimistic, useRef } from 'react'
import { send } from './actions.js'

export function Thread({ messages }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,16 @@ const app = next({})

The above `next` import is a function that receives an object with the following options:

- `dev`: `Boolean` - Whether or not to launch Next.js in dev mode. Defaults to `false`
- `dir`: `String` - Location of the Next.js project. Defaults to `'.'`
- `quiet`: `Boolean` - Hide error messages containing server information. Defaults to `false`
- `conf`: `object` - The same object you would use in [next.config.js](/docs/pages/api-reference/next-config-js). Defaults to `{}`
| Option | Type | Description |
| -------------- | ------------------ | ------------------------------------------------------------------------------------------------------------- |
| `conf` | `Object` | The same object you would use in [next.config.js](/docs/pages/api-reference/next-config-js). Defaults to `{}` |
| `customServer` | `Boolean` | (_Optional_) Set to false when the server was created by Next.js |
| `dev` | `Boolean` | (_Optional_) Whether or not to launch Next.js in dev mode. Defaults to `false` |
| `dir` | `String` | (_Optional_) Location of the Next.js project. Defaults to `'.'` |
| `quiet` | `Boolean` | (_Optional_) Hide error messages containing server information. Defaults to `false` |
| `hostname` | `String` | (_Optional_) The hostname the server is running behind |
| `port` | `Number` | (_Optional_) The port the server is running behind |
| `httpServer` | `node:http#Server` | (_Optional_) The HTTP Server that Next.js is running behind |

The returned `app` can then be used to let Next.js handle requests as required.

Expand Down
2 changes: 1 addition & 1 deletion packages/next/src/client/components/app-router-headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const NEXT_URL = 'Next-Url' as const
export const FETCH_CACHE_HEADER = 'x-vercel-sc-headers' as const
export const RSC_CONTENT_TYPE_HEADER = 'text/x-component' as const
export const RSC_VARY_HEADER =
`${RSC}, ${NEXT_ROUTER_STATE_TREE}, ${NEXT_ROUTER_PREFETCH}` as const
`${RSC}, ${NEXT_ROUTER_STATE_TREE}, ${NEXT_ROUTER_PREFETCH}, ${NEXT_URL}` as const

export const FLIGHT_PARAMETERS = [
[RSC],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export async function fetchServerResponse(
[
headers[NEXT_ROUTER_PREFETCH] || '0',
headers[NEXT_ROUTER_STATE_TREE],
headers[NEXT_URL],
].join(',')
)

Expand Down
49 changes: 16 additions & 33 deletions packages/next/src/server/app-render/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
canSegmentBeOverridden,
matchSegment,
} from '../../client/components/match-segments'
import { ServerInsertedHTMLContext } from '../../shared/lib/server-inserted-html'
import { stripInternalQueries } from '../internal-utils'
import {
NEXT_ROUTER_PREFETCH,
Expand Down Expand Up @@ -78,6 +77,7 @@ import { warn } from '../../build/output/log'
import { appendMutableCookies } from '../web/spec-extension/adapters/request-cookies'
import { ComponentsType } from '../../build/webpack/loaders/next-app-loader'
import { ModuleReference } from '../../build/webpack/loaders/metadata/types'
import { createServerInsertedHTML } from './server-inserted-html'

export type GetDynamicParamFromSegment = (
// [slug] / [[slug]] / [...slug]
Expand Down Expand Up @@ -1448,29 +1448,11 @@ export async function renderToHTMLOrFlight(

const { HeadManagerContext } =
require('../../shared/lib/head-manager-context') as typeof import('../../shared/lib/head-manager-context')
const serverInsertedHTMLCallbacks: Set<() => React.ReactNode> = new Set()
function InsertedHTML({ children }: { children: JSX.Element }) {
// Reset addInsertedHtmlCallback on each render
const addInsertedHtml = React.useCallback(
(handler: () => React.ReactNode) => {
serverInsertedHTMLCallbacks.add(handler)
},
[]
)

return (
<HeadManagerContext.Provider
value={{
appDir: true,
nonce,
}}
>
<ServerInsertedHTMLContext.Provider value={addInsertedHtml}>
{children}
</ServerInsertedHTMLContext.Provider>
</HeadManagerContext.Provider>
)
}
// On each render, create a new `ServerInsertedHTML` context to capture
// injected nodes from user code (`useServerInsertedHTML`).
const { ServerInsertedHTMLProvider, renderServerInsertedHTML } =
createServerInsertedHTML()

getTracer().getRootSpanAttributes()?.set('next.route', pagePath)
const bodyResult = getTracer().wrap(
Expand Down Expand Up @@ -1506,9 +1488,16 @@ export async function renderToHTMLOrFlight(
}))

const content = (
<InsertedHTML>
<ServerComponentsRenderer asNotFound={asNotFound} />
</InsertedHTML>
<HeadManagerContext.Provider
value={{
appDir: true,
nonce,
}}
>
<ServerInsertedHTMLProvider>
<ServerComponentsRenderer asNotFound={asNotFound} />
</ServerInsertedHTMLProvider>
</HeadManagerContext.Provider>
)

let polyfillsFlushed = false
Expand Down Expand Up @@ -1553,13 +1542,6 @@ export async function renderToHTMLOrFlight(
ReactDOMServer: require('react-dom/server.edge'),
element: (
<>
{Array.from(serverInsertedHTMLCallbacks).map(
(callback, index) => (
<React.Fragment key={'_next_insert' + index}>
{callback()}
</React.Fragment>
)
)}
{polyfillsFlushed
? null
: polyfills?.map((polyfill) => {
Expand All @@ -1573,6 +1555,7 @@ export async function renderToHTMLOrFlight(
/>
)
})}
{renderServerInsertedHTML()}
{errorMetaTags}
</>
),
Expand Down
29 changes: 29 additions & 0 deletions packages/next/src/server/app-render/server-inserted-html.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Provider for the `useServerInsertedHTML` API to register callbacks to insert
// elements into the HTML stream.

import React from 'react'
import { ServerInsertedHTMLContext } from '../../shared/lib/server-inserted-html'

export function createServerInsertedHTML() {
const serverInsertedHTMLCallbacks: (() => React.ReactNode)[] = []
const addInsertedHtml = (handler: () => React.ReactNode) => {
serverInsertedHTMLCallbacks.push(handler)
}

return {
ServerInsertedHTMLProvider({ children }: { children: JSX.Element }) {
return (
<ServerInsertedHTMLContext.Provider value={addInsertedHtml}>
{children}
</ServerInsertedHTMLContext.Provider>
)
},
renderServerInsertedHTML() {
return serverInsertedHTMLCallbacks.map((callback, index) => (
<React.Fragment key={'__next_server_inserted__' + index}>
{callback()}
</React.Fragment>
))
},
}
}
Loading

0 comments on commit 579710b

Please sign in to comment.