diff --git a/docs/api-reference/edge-runtime.md b/docs/api-reference/edge-runtime.md new file mode 100644 index 0000000000000..95e3f914472a8 --- /dev/null +++ b/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 + +### 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 + +
+ + Middleware + Run code before a request is completed. + +
+ +
+ + Middleware API Reference + Learn more about the supported APIs for Middleware. + +
diff --git a/docs/api-reference/next/server.md b/docs/api-reference/next/server.md new file mode 100644 index 0000000000000..efe2d7a475af2 --- /dev/null +++ b/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 +``` + +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' +``` + +#### 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. + +`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 + +
+ + Edge Runtime + Learn more about the supported Web APIs available. + +
+ +
+ + Middleware + Run code before a request is completed. + +
diff --git a/docs/manifest.json b/docs/manifest.json index 6e713f16df66f..5f5b4e41748ec 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -105,6 +105,10 @@ } ] }, + { + "title": "Middleware", + "path": "/docs/middleware.md" + }, { "title": "Going to Production", "path": "/docs/going-to-production.md" @@ -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": [ diff --git a/docs/middleware.md b/docs/middleware.md new file mode 100644 index 0000000000000..ca24db42360c7 --- /dev/null +++ b/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) + +## 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 + +
+ + Middleware API Reference + Learn more about the supported APIs for Middleware. + +
+ +
+ + Edge Runtime + Learn more about the supported Web APIs available. + +