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

Update the Next.js Pages guide to use the latest tooling #13001

Merged
merged 4 commits into from
Feb 27, 2024
Merged
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
169 changes: 89 additions & 80 deletions content/pages/framework-guides/nextjs/deploy-a-nextjs-site.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ The initial deployment created via C3 is referred to as a [Direct Upload](/pages

## Configure and deploy a project without C3

If you already have a Next.js project or wish to manually create and deploy one without using C3, Cloudflare recommends that you use `@cloudflare/next-on-pages` and refer to its [README](https://github.com/cloudflare/next-on-pages/tree/main/packages/next-on-pages#cloudflarenext-on-pages) for instructions and additional information to help you develop and deploy your project.
If you already have a Next.js project or wish to manually create and deploy one without using C3, Cloudflare recommends that you use `@cloudflare/next-on-pages` and refer to its [README](https://github.com/cloudflare/next-on-pages/tree/main/packages/next-on-pages) for instructions and additional information to help you develop and deploy your project.

{{<render file="/_framework-guides/_git-integration.md">}}

Expand Down Expand Up @@ -87,7 +87,7 @@ Projects created with C3 have bindings for local development set up by default.

{{</Aside>}}

To set up bindings for use in local development, you will use the `setupDevBindings` function provided by [`@cloudflare/next-on-pages/next-dev`](https://github.com/cloudflare/next-on-pages/tree/main/internal-packages/next-dev). This function allows you to specify bindings that work locally, and are accessed the same way remote bindings are.
To set up bindings for use in local development, you will use the `setupDevPlatform` function provided by [`@cloudflare/next-on-pages/next-dev`](https://github.com/cloudflare/next-on-pages/tree/main/internal-packages/next-dev). `setupDevPlatform` sets up a platform emulation based on your project's [`wrangler.toml`](/workers/wrangler/configuration/) file that your Next.js application can make use of locally.

For example, to work with a KV binding locally, open the Next.js configuration file and add:

Expand All @@ -97,27 +97,19 @@ For example, to work with a KV binding locally, open the Next.js configuration f
```js
---
filename: next.config.mjs
highlight: [1, 6-18]
highlight: [1-7]
---
import { setupDevBindings } from '@cloudflare/next-on-pages/next-dev'
import { setupDevPlatform } from '@cloudflare/next-on-pages/next-dev'

/** @type {import('next').NextConfig} */
const nextConfig = {}

// we only need to use the function during development so Cloudflare can check `NODE_ENV`
// (note: this check is recommended but completely optional)
// note: the if statement is present because you
// only need to use the function during development
if (process.env.NODE_ENV === 'development') {
// call the function with the bindings you want to have access to
await setupDevBindings({
bindings: {
MY_KV: {
type: "kv",
id: "MY_KV",
},
},
})
await setupDevPlatform()
}

/** @type {import('next').NextConfig} */
const nextConfig = {}

export default nextConfig
```

Expand All @@ -127,55 +119,95 @@ export default nextConfig
```js
---
filename: next.config.js / next.config.cjs
highlight: [4-18]
highlight: [1-6]
---
/** @type {import('next').NextConfig} */
const nextConfig = {}

// we only need to use the function during development so we can check NODE_ENV
// (note: this check is recommended but completely optional)
// note: the if statement is present because you
// only need to use the function during development
if (process.env.NODE_ENV === "development") {
const { setupDevBindings } = require("@cloudflare/next-on-pages/next-dev")

// call the function with the bindings you want to have access to
setupDevBindings({
bindings: {
MY_KV: {
type: "kv",
id: "MY_KV",
},
},
})
const { setupDevPlatform } = require("@cloudflare/next-on-pages/next-dev")
setupDevPlatform()
}

/** @type {import('next').NextConfig} */
const nextConfig = {}

module.exports = nextConfig
```

{{</tab>}}
{{</tabs>}}

Make sure to have a `wrangler.toml` file at the root of your project with a declaration for a KV binding named `MY_KV`:

```toml
---
filename: wrangler.toml
highlight: [5-7]
---
name = "my-next-app"

compatibility_flags = ["nodejs_compat"]

[[kv_namespaces]]
binding = "MY_KV"
id = "<YOUR_KV_NAMESPACE_ID>"
```

### Set up bindings for a deployed application

To access bindings in a deployed application, you will need to [configure](/pages/functions/bindings/) any necessary bindings and connect them to your project via your project's settings page in the Cloudflare dashboard.

### Add bindings to Typescript projects
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved this section up because, for typescript project it is a prerequisite of the Access bindings in the application one


If your project is using TypeScript, you will want to set up proper type support so you can access your bindings in a type-safe and convenient manner.

To get proper type support, you need to create a new `env.d.ts` file in your project and extend the `CloudflareEnv` (used by `getRequestContext`) interface with your [bindings](/pages/functions/bindings/).

{{<Aside type="note">}}

Projects created with C3 have a default `env.d.ts` file.

{{</Aside>}}

The following is an example of how to add a `KVNamespace` binding:

```ts
---
filename: env.d.ts
highlight: [7]
---
interface CloudflareEnv {
// The KV Namespace binding type used here comes
// from `@cloudflare/workers-types`. To use it in such
// a way make sure that you have installed the package
// as a dev dependency and you have added it to your
//`tsconfig.json` file under `compilerOptions.types`.
MY_KV: KVNamespace
}
```

### Access bindings in the application

Local and remote bindings can be accessed directly from `process.env`. The following code example shows how to access them in a `hello` API route of an App Router application.
Local and remote bindings can be accessed using the [`getRequestContext` function](https://github.com/cloudflare/next-on-pages/blob/3846730c4a0d12/packages/next-on-pages/README.md#cloudflare-platform-integration) exposed by `@cloudflare/next-on-pages`. The following code example shows how to access them in a `hello` API route of an App Router application.

{{<tabs labels="js | ts">}}
{{<tab label="js" default="true">}}

```js
---
filename: app/api/hello/route.js
highlight: [3]
highlight: [1, 7]
---
import { getRequestContext } from '@cloudflare/next-on-pages'

// ...

export async function GET(request) {
// this is the KV binding you defined in the config file
const myKv = process.env.MY_KV;
// this is the KV binding you defined in the wrangler.toml file
const myKv = getRequestContext().env.MY_KV

// get a value from the namespace
const kvValue = await myKv.get(`kvTest`) || false;
const kvValue = await myKv.get(`kvTest`) || false

return new Response(`The value of kvTest in MY_KV is: ${kvValue}`)
}
Expand All @@ -187,14 +219,18 @@ export async function GET(request) {
```ts
---
filename: app/api/hello/route.ts
highlight: [3]
highlight: [1, 7]
---
import { getRequestContext } from '@cloudflare/next-on-pages'

// ...

export async function GET(request: NextRequest) {
// this is the KV binding you defined in the config file
const myKv = process.env.MY_KV;
// this is the KV binding you defined in the wrangler.toml file
const myKv = getRequestContext().env.MY_KV

// get a value from the namespace
const kvValue = await myKv.get(`kvTest`) || false;
const kvValue = await myKv.get(`kvTest`) || false

return new Response(`The value of kvTest in MY_KV is: ${kvValue}`)
}
Expand All @@ -203,40 +239,6 @@ export async function GET(request: NextRequest) {
{{</tab>}}
{{</tabs>}}

### Add bindings to TypeScript projects

{{<Aside type="note">}}

Projects created with C3 have a default `env.d.ts` file.

{{</Aside>}}

To get proper type support, you need to create a new `env.d.ts` file in your project and declare a [binding](/pages/functions/bindings/).

The following is an example of adding a `KVNamespace` binding:

```ts
---
filename: env.d.ts
highlight: [4-10]
---
declare global {
namespace NodeJS {
interface ProcessEnv {
// The KV Namespace binding type used here comes
// from `@cloudflare/workers-types`. To
// use it like so, make sure that you have installed
// the package as a dev dependency and you have added
// it to your `tsconfig.json` file under
// `compilerOptions.types`.
MY_KV: KVNamespace;
}
}
}

export {};
```

## `Image` component

The Cloudflare network does not provide the same image optimization support as the Vercel network does. Because of this, the Next.js' `<Image />` component behaves differently from how it would in the Vercel network.
Expand All @@ -262,7 +264,7 @@ To ensure that your application is being built in a manner that is fully compati
If you have created your project with C3, do this by running:

```sh
$ npm run pages:build && npm run pages:dev
$ npm run preview
```

If you have created your project without C3, run:
Expand All @@ -274,9 +276,16 @@ $ npx @cloudflare/next-on-pages@1
And preview your project by running:

```sh
$ npx wrangler pages dev .vercel/output/static --compatibility-flag=nodejs_compat
$ npx wrangler pages dev .vercel/output/static
```

{{<Aside type="note">}}

The [`wrangler pages dev`](/workers/wrangler/commands/#dev-1) command needs to run the application using the [`nodejs_compat`](/workers/configuration/compatibility-dates/#nodejs-compatibility-flag) compatibility flag. The `nodejs_compat` flag can be specified in either your project's `wrangler.toml` file or provided to the command as an inline argument: `--compatibility-flag=nodejs_compat`.

{{</Aside>}}


### Deploy your application and iterate

After you have previewed your application locally, you can deploy it to Cloudflare Pages (both via [Direct Uploads](/pages/get-started/direct-upload/) or [Git integration](/pages/configuration/git-integration/)) and iterate over the process to make new changes.
Expand Down
Loading