Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 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
9 changes: 9 additions & 0 deletions .changeset/grumpy-trainers-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@opennextjs/cloudflare": patch
---

make sure that instrumentation files work

currently [instrumentation files](https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation)
in applications built using the adapter are ignored, the changes here
make sure that those are instead properly included in the applications
3 changes: 2 additions & 1 deletion examples/common/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ const apps = [
// examples
"create-next-app",
"middleware",
"playground",
"playground14",
"playground15",
"vercel-blog-starter",
"vercel-commerce",
"ssg-app",
Expand Down
1 change: 0 additions & 1 deletion examples/playground/README.md

This file was deleted.

3 changes: 0 additions & 3 deletions examples/playground/e2e/playwright.config.ts

This file was deleted.

File renamed without changes.
File renamed without changes.
10 changes: 10 additions & 0 deletions examples/playground14/app/api/instrumentation/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NextResponse } from "next/server";

export const dynamic = "force-dynamic";

export function GET() {
return NextResponse.json({
"nodejs-instrumentation-setup": globalThis["__NODEJS_INSTRUMENTATION_SETUP"],
"edge-instrumentation-setup": globalThis["__EDGE_INSTRUMENTATION_SETUP"],
});
}
File renamed without changes.
File renamed without changes.
36 changes: 36 additions & 0 deletions examples/playground14/e2e/instrumentation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { test, expect } from "@playwright/test";
import { describe } from "node:test";

test.describe("instrumentation", () => {
test("the instrumentation register hook should work for the nodejs runtime", async ({ page }) => {
const res = await page.request.get("/api/instrumentation");
const respJson: Record<string, string> = await res.json();
expect(respJson["nodejs-instrumentation-setup"]).toEqual(
"this value has been set by calling the instrumentation `register` callback in the nodejs runtime"
);
});

test("the instrumentation register hook should work for the edge runtime", async ({ page }) => {
const res = await page.request.get("/middleware-instrumentation");
const respJson: Record<string, string> = await res.json();
expect(respJson["edge-instrumentation-setup"]).toEqual(
"this value has been set by calling the instrumentation `register` callback in the edge runtime"
);
});

// Note: we cannot test this since currently both runtimes share the same global scope
// (see: https://github.com/opennextjs/opennextjs-cloudflare/issues/408)
describe.skip("isolation", () => {
test("the instrumentation register hook nodejs logic should not effect edge routes", async ({ page }) => {
const res = await page.request.get("/middleware-instrumentation");
const respJson: Record<string, string> = await res.json();
expect(respJson["nodejs-instrumentation-setup"]).toBeUndefined();
});

test("the instrumentation register hook edge logic should not effect nodejs routes", async ({ page }) => {
const res = await page.request.get("/api/instrumentation");
const respJson: Record<string, string> = await res.json();
expect(respJson["edge-instrumentation-setup"]).toBeUndefined();
});
});
});
3 changes: 3 additions & 0 deletions examples/playground14/e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { configurePlaywright } from "../../common/config-e2e";

export default configurePlaywright("playground14", { isCI: !!process.env.CI });
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { configurePlaywright } from "../../common/config-e2e";

export default configurePlaywright("playground", {
export default configurePlaywright("playground14", {
isCI: !!process.env.CI,
isWorker: false,
});
15 changes: 15 additions & 0 deletions examples/playground14/instrumentation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function register() {
// Note: we register instrumentation for both the nodejs and edge runtime, we do that using the NEXT_RUNTIME env
// variable as recommended in the official docs:
// https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation#importing-runtime-specific-code

if (process.env.NEXT_RUNTIME === "nodejs") {
globalThis["__NODEJS_INSTRUMENTATION_SETUP"] =
"this value has been set by calling the instrumentation `register` callback in the nodejs runtime";
}

if (process.env.NEXT_RUNTIME === "edge") {
globalThis["__EDGE_INSTRUMENTATION_SETUP"] =
"this value has been set by calling the instrumentation `register` callback in the edge runtime";
}
}
12 changes: 12 additions & 0 deletions examples/playground14/middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { NextResponse } from "next/server";

export function middleware() {
return NextResponse.json({
"nodejs-instrumentation-setup": globalThis["__NODEJS_INSTRUMENTATION_SETUP"],
"edge-instrumentation-setup": globalThis["__EDGE_INSTRUMENTATION_SETUP"],
});
}

export const config = {
matcher: ["/middleware-instrumentation"],
};
14 changes: 14 additions & 0 deletions examples/playground14/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";

initOpenNextCloudflareForDev();

/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
// Generate source map to validate the fix for opennextjs/opennextjs-cloudflare#341
serverSourceMaps: true,
instrumentationHook: true,
},
};

export default nextConfig;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "playground",
"name": "playground14",
"version": "0.1.0",
"private": true,
"type": "module",
Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions examples/playground15/.dev.vars
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXTJS_ENV=development
1 change: 1 addition & 0 deletions examples/playground15/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TEST_ENV_VAR=TEST_VALUE
45 changes: 45 additions & 0 deletions examples/playground15/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

# wrangler
.wrangler

# playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
9 changes: 9 additions & 0 deletions examples/playground15/app/api/buildid/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Use headers to force a dynamic response
import { headers } from "next/headers";

export async function GET() {
const nextConfig = process.env.__NEXT_PRIVATE_STANDALONE_CONFIG
? JSON.parse(process.env.__NEXT_PRIVATE_STANDALONE_CONFIG)
: undefined;
return Response.json({ nextConfig, headers: headers() });
}
8 changes: 8 additions & 0 deletions examples/playground15/app/api/env/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This test relies on using `.dev.vars` to set the environment to `development`
// However `next build` is not passed an environment, so we do not want to cache
// the output.
export const dynamic = "force-dynamic";

export async function GET() {
return new Response(JSON.stringify(process.env));
}
21 changes: 21 additions & 0 deletions examples/playground15/app/api/hello/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { headers } from "next/headers";

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

export async function GET() {
const headersList = await headers();

const fromCloudflareContext = headersList.has("from-cloudflare-context");

if (!fromCloudflareContext) {
return new Response("Hello World!");
}

// Retrieve the bindings defined in wrangler.json
return new Response(getCloudflareContext().env.hello);
}

export async function POST(request: Request) {
const text = await request.text();
return new Response(`Hello post-World! body=${text}`);
}
8 changes: 8 additions & 0 deletions examples/playground15/app/api/instrumentation/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { NextResponse } from "next/server";

export function GET() {
return NextResponse.json({
"nodejs-instrumentation-setup": globalThis["__NODEJS_INSTRUMENTATION_SETUP"],
"edge-instrumentation-setup": globalThis["__EDGE_INSTRUMENTATION_SETUP"],
});
}
5 changes: 5 additions & 0 deletions examples/playground15/app/api/request/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { NextRequest } from "next/server";

export const GET = (request: NextRequest) => {
return new Response(JSON.stringify({ nextUrl: request.nextUrl.href, url: request.url }));
};
30 changes: 30 additions & 0 deletions examples/playground15/app/isr/[id]/dynamic/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Imported from https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration
interface Post {
id: string;
title: string;
content: string;
}

// Next.js will invalidate the cache when a
// request comes in, at most once every 1 hour.
export const revalidate = 3600;

// We'll prerender only the params from `generateStaticParams` at build time.
// If a request comes in for a path that hasn't been generated,
// Next.js will server-render the page on-demand.
export const dynamicParams = true;

export async function generateStaticParams() {
return [{ id: "1" }, { id: "2" }, { id: "3" }];
}

export default async function Page({ params }: { params: Promise<{ id: string }> }) {
const id = (await params).id;
const post: Post = await fetch(`https://api.vercel.app/blog/${id}`).then((res) => res.json());
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
);
}
29 changes: 29 additions & 0 deletions examples/playground15/app/isr/[id]/no-dynamic/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Imported from https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration
interface Post {
id: string;
title: string;
content: string;
}

// Next.js will invalidate the cache when a
// request comes in, at most once every 1 hour.
export const revalidate = 3600;

// We'll prerender only the params from `generateStaticParams` at build time.
// If a request comes in for a path that hasn't been generated, it will 404.
export const dynamicParams = false;

export async function generateStaticParams() {
return [{ id: "1" }, { id: "2" }, { id: "3" }];
}

export default async function Page({ params }: { params: Promise<{ id: string }> }) {
const id = (await params).id;
const post: Post = await fetch(`https://api.vercel.app/blog/${id}`).then((res) => res.json());
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
);
}
12 changes: 12 additions & 0 deletions examples/playground15/app/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const metadata = {
title: "API hello-world",
description: "a simple api hello-world app",
};

export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
65 changes: 65 additions & 0 deletions examples/playground15/app/og/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { ImageResponse } from "next/og";

export const dynamic = "force-dynamic";

export async function GET() {
try {
return new ImageResponse(
(
<div
style={{
backgroundColor: "black",
backgroundSize: "150px 150px",
height: "100%",
width: "100%",
display: "flex",
textAlign: "center",
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
flexWrap: "nowrap",
}}
>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
justifyItems: "center",
}}
>
<img
alt="Vercel"
height={200}
src="data:image/svg+xml,%3Csvg width='116' height='100' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M57.5 0L115 100H0L57.5 0z' /%3E%3C/svg%3E"
style={{ margin: "0 30px" }}
width={232}
/>
</div>
<div
style={{
fontSize: 60,
fontStyle: "normal",
letterSpacing: "-0.025em",
color: "white",
marginTop: 30,
padding: "0 120px",
lineHeight: 1.4,
whiteSpace: "pre-wrap",
}}
>
'next/og'
</div>
</div>
),
{
width: 1200,
height: 630,
}
);
} catch (e: any) {
return new Response("Failed to generate the image", {
status: 500,
});
}
}
7 changes: 7 additions & 0 deletions examples/playground15/app/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Home() {
return (
<main>
<p>Test misc Next features</p>
</main>
);
}
Loading