Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more docs. #30320

Merged
merged 9 commits into from Oct 26, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
103 changes: 103 additions & 0 deletions docs/api-reference/edge-runtime.md
@@ -0,0 +1,103 @@
---
description: The Next.js Edge Runtime is based on standard Web APIs. Learn more about the supported APIs available.
---

# Edge Runtime

The Next.js Edge Runtime is based on standard Web APIs, which is used by [Middleware](/docs/middleware.md).

## Runtime APIs

### Globals

- [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
- [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
- [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)

### Base64

- [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/atob): Decodes a string of data which has been encoded using base-64 encoding
- [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/btoa): Creates a base-64 encoded ASCII string from a string of binary data

### Encoding

- [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder): Takes a stream of code points as input and emits a stream of bytes (UTF8)
- [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder): Takes a stream of bytes as input and emit a stream of code points

### Environment

- `process.env`: Holds an object with all environment variables for both production and development in the exact same way as any other page or API in Next.js
leerob marked this conversation as resolved.
Show resolved Hide resolved

### Fetch

The [Web Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) can be used from the runtime, enabling you to use Middleware as a proxy, or connect to external storage APIs

A potential caveat to using the Fetch API in a Middleware function is latency. For example, if you have a Middleware function running a fetch request to New York, and a user accesses your site from London, the request will be resolved from the nearest Edge to the user (in this case, London), to the origin of the request, New York. There is a risk this could happen on every request, making your site slow to respond. When using the Fetch API, you _must_ make sure it does not run on every single request made.

### Streams

- [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream): Consists of a pair of streams: a writable stream known as its writable side, and a readable stream, known as its readable side. Writes to the writable side, result in new data being made available for reading from the readable side. Support for web streams is quite limited at the moment, although it is more extended in the development environment
- [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream): A readable stream of byte data
- [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream): A standard abstraction for writing streaming data to a destination, known as a sink

### Timers

- [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval): Schedules a function to execute every time a given number of milliseconds elapses
- [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval): Cancels the repeated execution set using `setInterval()`
- [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout): Schedules a function to execute in a given amount of time
- [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout): Cancels the delayed execution set using `setTimeout()`

### Web

- [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers): A [WHATWG](https://whatwg.org/) implementation of the headers API
- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL): A WHATWG implementation of the URL API.
- [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams): A WHATWG implementation of `URLSearchParams`

### Crypto

- [`Crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto): The `Crypto` interface represents basic cryptography features available in the current context
- [`crypto.randomUUID`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID): Lets you generate a v4 UUID using a cryptographically secure random number generator
- [`crypto.getRandomValues`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues): Lets you get cryptographically strong random values
- [`crypto.subtle`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/subtle): A read-only property that returns a [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) which can then be used to perform low-level cryptographic operations

### Logging

- [`console.debug`](https://developer.mozilla.org/en-US/docs/Web/API/console/debug): Outputs a message to the console with the log level debug
- [`console.info`](https://developer.mozilla.org/en-US/docs/Web/API/console/info): Informative logging of information. You may use string substitution and additional arguments with this method
- [`console.clear`](https://developer.mozilla.org/en-US/docs/Web/API/console/clear): Clears the console
- [`console.dir`](https://developer.mozilla.org/en-US/docs/Web/API/console/dir): Displays an interactive listing of the properties of a specified JavaScript object
- [`console.count`](https://developer.mozilla.org/en-US/docs/Web/API/console/count): Log the number of times this line has been called with the given label
- [`console.time`](https://developer.mozilla.org/en-US/docs/Web/API/console/time): Starts a timer with a name specified as an input parameter

## Unsupported APIs

The Edge Runtime has some restrictions including:

- Native Node.js APIs **are not supported**. For example, you can't read or write to the filesystem
- Node Modules _can_ be used, as long as they implement ES Modules and do not use any native Node.js APIs
- Calling `require` directly is **not allowed**. Use ES Modules instead

The following JavaScript language features are disabled, and **will not work:**

- [`eval`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval): Evaluates JavaScript code represented as a string
- [`new Function(evalString)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function): Creates a new function with the code provided as an argument

The following Web APIs are currently not supported, but will be in the future:

- [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController): Abort one or more Web requests when desired

## Related

<div class="card">
<a href="/docs/middleware.md">
<b>Middleware</b>
<small>Run code before a request is completed.</small>
</a>
</div>

<div class="card">
<a href="/docs/api-reference/next/server.md">
<b>Middleware API Reference</b>
<small>Learn more about the supported APIs for Middleware.</small>
</a>
</div>
106 changes: 106 additions & 0 deletions docs/api-reference/next/server.md
@@ -0,0 +1,106 @@
---
description: Use Middleware to run code before a request is completed.
---

# next/server

Middleware is created by using a `middleware` function that lives inside a `_middleware` file. The Middleware API is based upon the native [`FetchEvent`](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent), [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response), and [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) objects.

These native Web API objects are extended to give you more control over how you manipulate and configure a response, based on the incoming requests.

The function signature:

```ts
import type { NextFetchEvent } from 'next/server'
import type { NextRequest } from 'next/server'

export type Middleware = (
request: NextRequest,
event: NextFetchEvent
) => Promise<Response | undefined> | Response | undefined
```

The function can be a default export and as such, does **not** have to be named `middleware`. Though this is a convention. Also note that you only need to make the function `async` if you are running asynchronous code.

## NextFetchEvent

The `NextFetchEvent` object extends the native [`FetchEvent`](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent) object, and includes the [`waitUntil()`](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil) method.

The `waitUntil()` method can be used to prolong the execution of the function, after the response has been sent. In practice this means that you can send a response, then continue the function execution if you have other background work to make.

An example of _why_ you would use `waitUntil()` is integrations with logging tools such as [Sentry](https://sentry.io) or [DataDog](https://www.datadoghq.com). After the response has been sent, you can send logs of response times, errors, API call durations or overall performance metrics.

The `event` object is fully typed and can be imported from `next/server`.

```ts
import { NextFetchEvent } from 'next/server'
```

#### NextRequest

The `NextRequest` object is an extension of the native [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) interface, with the following added methods and properties:

- `cookies` - Has the cookies from the `Request`
- `nextUrl` - Includes an extended, parsed, URL object that gives you access to Next.js specific properties such as `pathname`, `basePath`, `trailingSlash` and `i18n`
- `geo` - Has the geo location from the `Request`
- `geo.country` - The country code
- `geo.region` - The region code
- `geo.city` - The city
- `geo.latitude` - The latitude
- `geo.longitude` - The longitude
- `ip` - Has the IP address of the `Request`
- `ua` - Has the user agent

You can use the `NextRequest` object as a direct replacement for the native `Request` interface, giving you more control over how you manipulate the request.

`NextRequest` is fully typed and can be imported from `next/server`.

```ts
import type { NextRequest } from 'next/server'
```

leerob marked this conversation as resolved.
Show resolved Hide resolved
#### NextResponse

The `NextResponse` object is an extension of the native [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) interface, with the following added methods and properties:

- `cookies` - An object with the cookies in the `Response`
- `redirect()` - Returns a `NextResponse` with a redirect set
- `rewrite()` - Returns a `NextResponse` with a rewrite set
- `next()` - Returns a `NextResponse` that will continue the middleware chain

All methods above return a `NextResponse` object that only takes effect if it's returned in the middleware function.

leerob marked this conversation as resolved.
Show resolved Hide resolved
`NextResponse` is fully typed and can be imported from `next/server`.

```ts
import { NextResponse } from 'next/server'
```

### Why does redirect use 307 and 308?

When using `redirect()` you may notice that the status codes used are `307` for a temporary redirect, and `308` for a permanent redirect. While traditionally a `302` was used for a temporary redirect, and a `301` for a permanent redirect, many browsers changed the request method of the redirect, from a `POST` to `GET` request when using a `302`, regardless of the origins request method.

Taking the following example of a redirect from `/users` to `/people`, if you make a `POST` request to `/users` to create a new user, and are conforming to a `302` temporary redirect, the request method will be changed from a `POST` to a `GET` request. This doesn't make sense, as to create a new user, you should be making a `POST` request to `/people`, and not a `GET` request.

The introduction of the `307` status code means that the request method is preserved as `POST`.

- `302` - Temporary redirect, will change the request method from `POST` to `GET`
- `307` - Temporary redirect, will preserve the request method as `POST`

The `redirect()` method uses a `307` by default, instead of a `302` temporary redirect, meaning your requests will _always_ be preserved as `POST` requests.

## Related

<div class="card">
<a href="/docs/api-reference/edge-runtime.md">
<b>Edge Runtime</b>
<small>Learn more about the supported Web APIs available.</small>
</a>
</div>

<div class="card">
<a href="/docs/middleware.md">
<b>Middleware</b>
<small>Run code before a request is completed.</small>
</a>
</div>
12 changes: 12 additions & 0 deletions docs/manifest.json
Expand Up @@ -105,6 +105,10 @@
}
]
},
{
"title": "Middleware",
"path": "/docs/middleware.md"
},
{
"title": "Going to Production",
"path": "/docs/going-to-production.md"
Expand Down Expand Up @@ -288,6 +292,14 @@
"title": "next/amp",
"path": "/docs/api-reference/next/amp.md"
},
{
"title": "next/server",
"path": "/docs/api-reference/next/server.md"
},
{
"title": "Edge Runtime",
"path": "/docs/api-reference/next/edge-runtime.md"
},
{
"title": "Data Fetching",
"routes": [
Expand Down
93 changes: 93 additions & 0 deletions docs/middleware.md
@@ -0,0 +1,93 @@
---
description: Learn how to use Middleware in Next.js to run code before a request is completed.
---

# Middleware

Middleware enables you to use code over configuration. This gives you full flexibility in Next.js, because you can run code before a request is completed. Based on the user's incoming request, you can modify the response by rewriting, redirecting, adding headers, or even streaming HTML.

## Usage

1. Install the latest version of Next.js:

```jsx
npm install next@latest
```

2. Then, create a `_middleware.ts` file under your `/pages` directory.

3. Finally, export a middleware function from the `_middleware.ts` file.

```jsx
// pages/_middleware.ts

import type { NextFetchEvent, NextRequest } from 'next/server'

export function middleware(req: NextRequest, ev: NextFetchEvent) {
return new Response('Hello, world!')
}
```

In this example, we use the standard Web API Response ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Response)).

## Examples

Middleware can be used for anything that shares logic for a set of pages, including:

- [Authentication](https://github.com/vercel/examples/tree/main/edge-functions)
- [Bot protection](https://github.com/vercel/examples/tree/main/edge-functions)
- [Redirects and rewrites](https://github.com/vercel/examples/tree/main/edge-functions)
- [Handling unsupported browsers](https://github.com/vercel/examples/tree/main/edge-functions)
- [Feature flags and A/B tests](https://github.com/vercel/examples/tree/main/edge-functions)
- [Server-side analytics](https://github.com/vercel/examples/tree/main/edge-functions)
- [Advanced i18n routing requirements](https://github.com/vercel/examples/tree/main/edge-functions)
- [Logging](https://github.com/vercel/examples/tree/main/edge-functions)
leerob marked this conversation as resolved.
Show resolved Hide resolved

## Execution Order

If your Middleware is created in `/pages/_middleware.js`, it will run on all routes within the `/pages` directory. The below example assumes you have `about.tsx` and `teams.tsx` routes.

```bash
- package.json
- /pages
_middleware.ts # Will run on all routes under /pages
index.tsx
about.tsx
teams.tsx
```

If you _do_ have sub-directories with nested routes, Middleware will run from the top down. For example, if you have `/pages/about/_middleware.ts` and `/pages/about/team/_middleware.ts`, `/about` will run first and then `/about/team`. The below example shows how this works with a nested routing structure.

```bash
- package.json
- /pages
index.tsx
- /about
_middleware.ts # Will run first
about.tsx
- /teams
_middleware.ts # Will run second
teams.tsx
```

Middleware runs directly after `redirects` and `headers`, before the first filesystem lookup. This excludes `/_next` files.

## Deployment

Middleware uses a [strict runtime](/docs/api-reference/edge-runtime.md) that supports standard Web APIs like `fetch`. This works out of the box using `next start`, as well as on Edge platforms like Vercel, which use [Edge Functions](http://www.vercel.com/edge).

## Related

<div class="card">
<a href="/docs/api-reference/next/server.md">
<b>Middleware API Reference</b>
<small>Learn more about the supported APIs for Middleware.</small>
</a>
</div>

<div class="card">
<a href="/docs/api-reference/edge-runtime.md">
<b>Edge Runtime</b>
<small>Learn more about the supported Web APIs available.</small>
</a>
</div>