From bc46b7eb1e9b75399d4b230f22f2e45e580be352 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Tue, 27 Feb 2024 11:01:49 +0000 Subject: [PATCH] Update the Next.js Pages guide to use the latest tooling (#13001) * update the Next.js Pages guide to use the latest tooling update the Next.js Pages guide to use the latest tooling consistently to the changes made in C3: https://github.com/cloudflare/workers-sdk/pull/5009 Such changes include: - renaming `setupDevBindings` with `setupDevPlatform` - updating the bindings access to use `getRequestContext` - update the C3 scaffolded script names - update the `env.d.ts` file content --------- Co-authored-by: Kate Tungusova <70746074+deadlypants1973@users.noreply.github.com> --- .../nextjs/deploy-a-nextjs-site.md | 169 +++++++++--------- 1 file changed, 89 insertions(+), 80 deletions(-) diff --git a/content/pages/framework-guides/nextjs/deploy-a-nextjs-site.md b/content/pages/framework-guides/nextjs/deploy-a-nextjs-site.md index dc6ab608642d613..aa8bfa2d8560daa 100644 --- a/content/pages/framework-guides/nextjs/deploy-a-nextjs-site.md +++ b/content/pages/framework-guides/nextjs/deploy-a-nextjs-site.md @@ -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. {{}} @@ -87,7 +87,7 @@ Projects created with C3 have bindings for local development set up by default. {{}} -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: @@ -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 ``` @@ -127,40 +119,76 @@ 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 ``` {{}} {{}} +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 = "" +``` + ### 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 + +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/). + +{{}} + +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. {{}} {{}} @@ -168,14 +196,18 @@ Local and remote bindings can be accessed directly from `process.env`. The follo ```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}`) } @@ -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}`) } @@ -203,40 +239,6 @@ export async function GET(request: NextRequest) { {{}} {{}} -### Add bindings to TypeScript projects - -{{}} - -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' `` component behaves differently from how it would in the Vercel network. @@ -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: @@ -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 ``` +{{}} + + ### 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.