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

introduce new initOpenNextCloudflareForDev utility and make getCloudflareContext synchronous #265

Merged
merged 20 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
60a6296
introduce new `initOpenNextCloudflareForDev` utility and make `getClo…
dario-piotrowicz Jan 17, 2025
30a9f89
Apply suggestions from code review
dario-piotrowicz Jan 23, 2025
a9b6b3a
remove `getInternalGlobalThis` function
dario-piotrowicz Jan 23, 2025
26ae6de
mention that `initOpenNextCloudflareForDev` doesn't need to be `await`ed
dario-piotrowicz Jan 23, 2025
6c29ca7
remove `init` awaiting in kvCache
dario-piotrowicz Jan 24, 2025
6c54ae3
update test so that ordering of env keys does not matter
dario-piotrowicz Jan 24, 2025
c91b369
fixup! update kvCache
vicb Jan 24, 2025
6e9e500
fixup! drop async
vicb Jan 24, 2025
a3b4551
remove `getCloudflareContext` example from changeset
dario-piotrowicz Jan 24, 2025
1d76b5f
apply requested timout change
dario-piotrowicz Jan 24, 2025
e942a91
amend wrong timeout
dario-piotrowicz Jan 24, 2025
8b8a25d
update process declaration in playwright configs
dario-piotrowicz Jan 24, 2025
7bf0790
simplify middleware e2e check
dario-piotrowicz Jan 24, 2025
3b1deb3
import type from "node:process"
dario-piotrowicz Jan 24, 2025
9990519
update changeset
dario-piotrowicz Jan 24, 2025
a973ae5
Apply suggestions from code review
dario-piotrowicz Jan 24, 2025
612f3f7
update changeset to minor
dario-piotrowicz Jan 24, 2025
6473145
remove getting started info from README and redirect to official docs
dario-piotrowicz Jan 24, 2025
7a272cb
Update examples/middleware/middleware.ts
dario-piotrowicz Jan 27, 2025
ed349ca
remove known issues section from readme
dario-piotrowicz Jan 27, 2025
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
28 changes: 28 additions & 0 deletions .changeset/chilly-dryers-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
"@opennextjs/cloudflare": minor
---

introduce new `initOpenNextCloudflareForDev` utility and make `getCloudflareContext` synchronous

this change introduces a new `initOpenNextCloudflareForDev` function that must called in the [Next.js config file](https://nextjs.org/docs/app/api-reference/config/next-config-js) to integrate the Next.js dev server with the open-next Cloudflare adapter.

Also makes `getCloudflareContext` synchronous.

Additionally the `getCloudflareContext` can now work during local development (`next dev`) in the edge runtime (including middlewares).

Moving forward we'll recommend that all applications include the use of the `initOpenNextCloudflareForDev` utility in their config file (there is no downside in doing so and it only effect local development).

Example:

```js
// next.config.mjs

import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";

initOpenNextCloudflareForDev();

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

export default nextConfig;
```
5 changes: 2 additions & 3 deletions examples/api/app/api/hello/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ export async function GET() {
return new Response("Hello World!");
}

// Retrieve the bindings defined in wrangler.toml
const { env } = await getCloudflareContext();
return new Response(env.hello);
// Retrieve the bindings defined in wrangler.json
return new Response(getCloudflareContext().env.hello);
}

export async function POST(request: Request) {
Expand Down
4 changes: 3 additions & 1 deletion examples/api/e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineConfig, devices } from "@playwright/test";
import type nodeProcess from "node:process";

declare var process: { env: Record<string, string> };
declare const process: typeof nodeProcess;

/**
* See https://playwright.dev/docs/test-configuration.
Expand Down Expand Up @@ -49,5 +50,6 @@ export default defineConfig({
command: "pnpm preview:worker",
url: "http://localhost:8770",
reuseExistingServer: !process.env.CI,
timeout: 70_000,
},
});
3 changes: 2 additions & 1 deletion examples/api/e2e/playwright.dev.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineConfig, devices } from "@playwright/test";
import type nodeProcess from "node:process";

declare var process: { env: Record<string, string> };
declare const process: typeof nodeProcess;

/**
* See https://playwright.dev/docs/test-configuration.
Expand Down
4 changes: 4 additions & 0 deletions examples/api/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";

initOpenNextCloudflareForDev();

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

Expand Down
4 changes: 3 additions & 1 deletion examples/create-next-app/e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineConfig, devices } from "@playwright/test";
import type nodeProcess from "node:process";

declare const process: { env: Record<string, string> };
declare const process: typeof nodeProcess;

/**
* See https://playwright.dev/docs/test-configuration.
Expand Down Expand Up @@ -49,5 +50,6 @@ export default defineConfig({
command: "pnpm preview:worker",
url: "http://localhost:8771",
reuseExistingServer: !process.env.CI,
timeout: 70_000,
},
});
4 changes: 4 additions & 0 deletions examples/create-next-app/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";

initOpenNextCloudflareForDev();

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

Expand Down
24 changes: 23 additions & 1 deletion examples/middleware/app/middleware/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
import { headers } from "next/headers";

export default function MiddlewarePage() {
return <h1>Via middleware</h1>;
const cloudflareContextHeader = headers().get("x-cloudflare-context");

return (
<>
<h1>Via middleware</h1>
<p>
The value of the <i>x-cloudflare-context</i> header is: <br />
<span
style={{
display: "inline-block",
margin: "1rem 2rem",
color: "grey",
fontSize: "1.2rem",
}}
data-testid="cloudflare-context-header"
>
{cloudflareContextHeader}
</span>
</p>
</>
);
}
9 changes: 9 additions & 0 deletions examples/middleware/e2e/cloudflare-context.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { test, expect } from "@playwright/test";

test("middlewares have access to the cloudflare context", async ({ page }) => {
await page.goto("/middleware");
const cloudflareContextHeaderElement = page.getByTestId("cloudflare-context-header");
expect(await cloudflareContextHeaderElement.textContent()).toContain(
"typeof `cloudflareContext.env` = object"
);
});
4 changes: 3 additions & 1 deletion examples/middleware/e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineConfig, devices } from "@playwright/test";
import type nodeProcess from "node:process";

declare const process: { env: Record<string, string> };
declare const process: typeof nodeProcess;

/**
* See https://playwright.dev/docs/test-configuration.
Expand Down Expand Up @@ -49,5 +50,6 @@ export default defineConfig({
command: "pnpm preview:worker",
url: "http://localhost:8774",
reuseExistingServer: !process.env.CI,
timeout: 70_000,
},
});
54 changes: 54 additions & 0 deletions examples/middleware/e2e/playwright.dev.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { defineConfig, devices } from "@playwright/test";
import type nodeProcess from "node:process";

declare const process: typeof nodeProcess;

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:3334",

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},

/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},

{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
},

{
name: "webkit",
use: { ...devices["Desktop Safari"] },
},
],

/* Run your local dev server before starting the tests */
webServer: {
command: "pnpm dev --port 3334",
url: "http://localhost:3334",
reuseExistingServer: !process.env.CI,
},
});
16 changes: 15 additions & 1 deletion examples/middleware/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { NextRequest, NextResponse, NextFetchEvent } from "next/server";
import { clerkMiddleware } from "@clerk/nextjs/server";

import { getCloudflareContext } from "@opennextjs/cloudflare";

export function middleware(request: NextRequest, event: NextFetchEvent) {
console.log("middleware");
if (request.nextUrl.pathname === "/about") {
Expand All @@ -16,7 +18,19 @@ export function middleware(request: NextRequest, event: NextFetchEvent) {
})(request, event);
}

return NextResponse.next();
const requestHeaders = new Headers(request.headers);
const cloudflareContext = getCloudflareContext();

requestHeaders.set(
"x-cloudflare-context",
`typeof \`cloudflareContext.env\` = ${typeof cloudflareContext.env}`
);

return NextResponse.next({
request: {
headers: requestHeaders,
},
});
}

export const config = {
Expand Down
4 changes: 4 additions & 0 deletions examples/middleware/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";

initOpenNextCloudflareForDev();

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

Expand Down
3 changes: 2 additions & 1 deletion examples/middleware/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"build:worker": "pnpm opennextjs-cloudflare",
"dev:worker": "wrangler dev --port 8774 --inspector-port 9334",
"preview:worker": "pnpm build:worker && pnpm dev:worker",
"e2e": "playwright test -c e2e/playwright.config.ts"
"e2e": "playwright test -c e2e/playwright.config.ts",
"e2e:dev": "playwright test -c e2e/playwright.dev.config.ts"
},
"dependencies": {
"@clerk/nextjs": "6.9.6",
Expand Down
6 changes: 5 additions & 1 deletion examples/middleware/wrangler.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS"
}
},
"vars": {
"MY_VAR": "my-var"
},
"kv_namespaces": [{ "binding": "MY_KV", "id": "<id>" }]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"prettier:fix": "prettier --write .",
"lint:check": "pnpm -r lint:check",
"lint:fix": "pnpm -r lint:fix",
"fix": "pnpm prettier:fix && pnpm lint:fix",
"ts:check": "pnpm -r ts:check",
"test": "pnpm -r test",
"code:checks": "pnpm prettier:check && pnpm lint:check && pnpm ts:check",
Expand Down
67 changes: 1 addition & 66 deletions packages/cloudflare/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,72 +6,7 @@ Deploy Next.js apps to Cloudflare!

## Get started

You can use [`create-next-app`](https://nextjs.org/docs/pages/api-reference/cli/create-next-app) to start a new application or take an existing Next.js application and deploy it to Cloudflare using the following few steps:

## Configure your app

- add the following `devDependencies` to the `package.json`:

```bash
npm add -D wrangler@latest @opennextjs/cloudflare
# or
pnpm add -D wrangler@latest @opennextjs/cloudflare
# or
yarn add -D wrangler@latest @opennextjs/cloudflare
# or
bun add -D wrangler@latest @opennextjs/cloudflare
```

- add a `wrangler.json` at the root of your project

```json
{
"$schema": "node_modules/wrangler/config-schema.json",
"main": ".open-next/worker.js",
"name": "<your-app-name>",
"compatibility_date": "2024-12-30",
"compatibility_flags": ["nodejs_compat"],
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS"
}
}
```

- add a `open-next.config.ts` at the root of your project:

```ts
import type { OpenNextConfig } from "open-next/types/open-next";

const config: OpenNextConfig = {
default: {
override: {
wrapper: "cloudflare-node",
converter: "edge",
// Unused implementation
incrementalCache: "dummy",
tagCache: "dummy",
queue: "dummy",
},
},

middleware: {
external: true,
override: {
wrapper: "cloudflare-edge",
converter: "edge",
proxyExternalRequest: "fetch",
},
},
};

export default config;
```

## Known issues

- `▲ [WARNING] Suspicious assignment to defined constant "process.env.NODE_ENV" [assign-to-define]` can safely be ignored
- Maybe more, still experimental...
To get started with the adapter visit the [official get started documentation](https://opennext.js.org/cloudflare/get-started).
dario-piotrowicz marked this conversation as resolved.
Show resolved Hide resolved

## Local development

Expand Down
Loading
Loading