Skip to content
Open
Show file tree
Hide file tree
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
42 changes: 42 additions & 0 deletions apps/site/cloudflare/worker-entrypoint.ts
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@dario-piotrowicz we had Sentry in the past with good chunk of customization, could you please go through GitHub history and check it out (just to compare what we had at the time)

Copy link
Copy Markdown
Member

@MattIPv4 MattIPv4 Apr 20, 2026

Choose a reason for hiding this comment

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

We should replicate the settings that we use on the release worker, as we know those settings work for us. I don't think historical settings from the Next.js site make much sense as a reference point, given this is Worker instrumentation.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't see settings set for the release worker: https://github.com/nodejs/release-cloudflare-worker/blob/main/src/worker.ts 👀 am I looking in the wrong place? or do you mean those Sentry.setTags?

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Note: this custom worker-entrypoint is used so that the worker can include sentry support
// and it has been written by following:
// - the official open-next docs: https://opennext.js.org/cloudflare/howtos/custom-worker
// - the official sentry docs: https://docs.sentry.io/platforms/javascript/guides/cloudflare

import { withSentry } from '@sentry/cloudflare';

import type { ExecutionContext } from '@cloudflare/workers-types';

import { default as handler } from '../.open-next/worker.js';

export default withSentry(
(env: {
/**
* Sentry DSN, used for error monitoring
* If missing, Sentry isn't used
*/
SENTRY_DSN?: string;
}) => ({
dsn: env.SENTRY_DSN,
Comment thread
flakey5 marked this conversation as resolved.
// Adds request headers and IP for users, for more info visit:
// https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration/options/#sendDefaultPii
sendDefaultPii: true,
Comment thread
ovflowd marked this conversation as resolved.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@dario-piotrowicz disable this please

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we need to disable this? This is pretty important for allowing Sentry to properly tell us the scope of an issue in terms of user impact etc.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

mh... shall we disable it just to get sentry integrated and possibly re-enable it later when/if we want? 🤔

// Enable logs to be sent to Sentry
enableLogs: true,
// Set tracesSampleRate to 0.05 to capture 5% of spans for tracing.
// Learn more at
// https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration/options/#tracesSampleRate
tracesSampleRate: 0.05,
}),
{
async fetch(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What is this fetch override, ooc? 👀

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This fetch calls the actual open-next worker

request: Request,
env: Record<string, unknown>,
ctx: ExecutionContext
) {
return handler.fetch(request, env, ctx);
},
}
);

export { DOQueueHandler } from '../.open-next/worker.js';
10 changes: 9 additions & 1 deletion apps/site/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ import baseConfig from '../../eslint.config.js';

export default baseConfig.concat([
{
ignores: ['pages/en/blog/**/*.{md,mdx}/**', 'public', 'next-env.d.ts'],
ignores: [
'pages/en/blog/**/*.{md,mdx}/**',
'public',
'next-env.d.ts',
// The worker entrypoint is bundled by wrangler, not tsc. Its imports
// trigger a tsc crash (see tsconfig.json), so it is excluded from both
// type checking and ESLint's type-aware linting.
'cloudflare/worker-entrypoint.ts',
],
Comment thread
ovflowd marked this conversation as resolved.
},

eslintReact.configs['recommended-typescript'],
Expand Down
4 changes: 3 additions & 1 deletion apps/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@
"typescript": "catalog:",
"typescript-eslint": "~8.57.2",
"user-agent-data-types": "0.4.2",
"wrangler": "^4.77.0"
"wrangler": "^4.77.0",
"@cloudflare/workers-types": "^4.20260418.1",
"@sentry/cloudflare": "^10.49.0"
Comment on lines +110 to +112

This comment was marked as low quality.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder how much this bloats our dependencies. I wonder if we should have a specific package for our OpenNext implementation on this monorepo. So that we move all the cloudflare specifics to a specific apps/site-cloudflare or something like that?

This would reduce the need for local development and even other environments to install and pull and test all things unrelated to the default installation of the website?

wdyt @dario-piotrowicz @nodejs/web-infra?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I can't imagine the extra deps being an issue for local development 🤔

Also even if they were in their specific package, as long as they were in the monorepo they'd still be pulled down/installed on pnpm install invocations no? 🤔

},
"imports": {
"#site/*": [
Expand Down
11 changes: 10 additions & 1 deletion apps/site/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,14 @@
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": ["node_modules", ".next"]
"exclude": [
"node_modules",
".next",
".open-next",
// The worker entrypoint is bundled by wrangler (not tsc). Its imports of
// @sentry/cloudflare and .open-next/worker.js trigger an infinite-recursion
// crash in the TypeScript compiler (v5.9) during type resolution of
// @cloudflare/workers-types, so we exclude it from type checking.
"cloudflare/worker-entrypoint.ts"
Comment thread
ovflowd marked this conversation as resolved.
]
}
7 changes: 6 additions & 1 deletion apps/site/wrangler.jsonc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "./node_modules/wrangler/config-schema.json",
"main": ".open-next/worker.js",
"main": "./cloudflare/worker-entrypoint.ts",
"name": "nodejs-website",
"compatibility_date": "2024-11-07",
"compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
Expand Down Expand Up @@ -59,4 +59,9 @@
"new_sqlite_classes": ["DOQueueHandler"],
},
],
"version_metadata": {
// CF_VERSION_METADATA used for sentry
// See: https://docs.sentry.io/platforms/javascript/guides/cloudflare/#release-configuration-optional
"binding": "CF_VERSION_METADATA",
},
}
21 changes: 20 additions & 1 deletion docs/cloudflare-build-and-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ For more details, refer to the [Wrangler documentation](https://developers.cloud

Key configurations include:

- `main`: Points to the worker generated by the OpenNext adapter.
- `main`: Points to a custom worker entry point ([`site/cloudflare/worker-entrypoint.ts`](../apps/site/cloudflare/worker-entrypoint.ts)) that wraps the OpenNext-generated worker (see [Custom Worker Entry Point](#custom-worker-entry-point) and [Sentry](#sentry) below).
- `account_id`: Specifies the Cloudflare account ID. This is not required for local previews but is necessary for deployments. You can obtain an account ID for free by signing up at [dash.cloudflare.com](https://dash.cloudflare.com/login).
- This is currently set to `fb4a2d0f103c6ff38854ac69eb709272`, which is the ID of a Cloudflare account controlled by Node.js, and used for testing.
- `build`: Defines the build command to generate the Node.js filesystem polyfills required for the application to run on Cloudflare Workers. This uses the [`@flarelabs/wrangler-build-time-fs-assets-polyfilling`](https://github.com/flarelabs-net/wrangler-build-time-fs-assets-polyfilling) package.
- `alias`: Maps aliases for the Node.js filesystem polyfills generated during the build process.
- `r2_buckets`: Contains a single R2 binding definition for `NEXT_INC_CACHE_R2_BUCKET`. This is used to implement the Next.js incremental cache.
- This is currently set up to a R2 bucket in the aforementioned Cloudflare testing account.
- `durable_objects`: Contains a single DurableObject binding definition for `NEXT_CACHE_DO_QUEUE`. This is used to implement the Open-next cache queue.
- `version_metadata`: Contains a binding for `CF_VERSION_METADATA`, used for Sentry release configuration (see [Sentry](#sentry) below).

### OpenNext Configuration

Expand Down Expand Up @@ -54,6 +55,24 @@ The custom loader can be found at [`site/cloudflare/image-loader.ts`](../apps/si

For more details on this see: https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/#global-loader

### Custom Worker Entry Point

Instead of directly using the OpenNext-generated worker (`.open-next/worker.js`), the application uses a custom worker entry point at [`site/cloudflare/worker-entrypoint.ts`](../apps/site/cloudflare/worker-entrypoint.ts). This allows customizing the worker's behavior before requests are handled (currently used to integrate [Sentry](#sentry) error monitoring).

The custom entry point imports the OpenNext-generated handler from `.open-next/worker.js` and re-exports the `DOQueueHandler` Durable Object needed by the application.

For more details on custom workers, refer to the [OpenNext custom worker documentation](https://opennext.js.org/cloudflare/howtos/custom-worker).

### Sentry

Error monitoring is provided by [Sentry](https://sentry.io/) via the [`@sentry/cloudflare`](https://www.npmjs.com/package/@sentry/cloudflare) package.

The [custom worker entry point](#custom-worker-entry-point) wraps the OpenNext handler with `Sentry.withSentry()`, which instruments incoming requests for error and performance tracking.

The `version_metadata` binding (`CF_VERSION_METADATA`) in the Wrangler configuration enables Sentry [release configuration](https://docs.sentry.io/platforms/javascript/guides/cloudflare/#release-configuration-optional), allowing errors to be associated with specific worker versions.

Comment thread
ovflowd marked this conversation as resolved.
For more details, refer to the [Sentry Cloudflare guide](https://docs.sentry.io/platforms/javascript/guides/cloudflare).

## Scripts

Preview and deployment of the website targeting the Cloudflare network is implemented via the following two commands:
Expand Down
Loading
Loading