Skip to content

Commit f870073

Browse files
authored
fix(astro): Do not inject withSentry into Cloudflare Pages (#19558)
When running on Cloudflare Pages the `withSentry` function got bundled and wrapped into the `index.js`. This actually didn't cause any problems during the runtime, but it just added unnecessary code into the bundle. This removes now the automatic wrapping, which is required for Cloudflare Workers only. By adding the plugin `sentryCloudflareNodeWarningPlugin` we also remove tons of warnings like following when building for Cloudflare Pages: ``` 11:20:40 [WARN] [vite] [plugin vite:resolve] Automatically externalized node built-in module "node:diagnostics_channel" imported from "node_modules/.pnpm/@sentry+node@10.40.0/node_modules/@sentry/node/build/esm/integrations/tracing/fastify/index.js". Consider adding it to environments.ssr.external if it is intended. 11:20:40 [WARN] [vite] [plugin vite:resolve] Automatically externalized node built-in module "node:diagnostics_channel" imported from "node_modules/.pnpm/@sentry+node-core@10.40.0_@opentelemetry+api@1.9.0_@opentelemetry+context-async-hooks@2_feb79575758996d9eeb93d3eb9a5534b/node_modules/@sentry/node-core/build/esm/integrations/http/httpServerIntegration.js". Consider adding it to environments.ssr.external if it is intended. ``` Closes #19559 (added automatically)
1 parent 552187d commit f870073

File tree

2 files changed

+386
-2
lines changed

2 files changed

+386
-2
lines changed

packages/astro/src/integration/index.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
163163
}
164164

165165
const isCloudflare = config?.adapter?.name?.startsWith('@astrojs/cloudflare');
166+
const isCloudflareWorkers = isCloudflare && !isCloudflarePages();
166167

167168
if (isCloudflare) {
168169
try {
@@ -191,8 +192,8 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
191192
injectScript('page-ssr', buildServerSnippet(options || {}));
192193
}
193194

194-
if (isCloudflare && command !== 'dev') {
195-
// For Cloudflare production builds, additionally use a Vite plugin to:
195+
if (isCloudflareWorkers && command !== 'dev') {
196+
// For Cloudflare Workers production builds, additionally use a Vite plugin to:
196197
// 1. Import the server config at the Worker entry level (so Sentry.init() runs
197198
// for ALL requests, not just SSR pages — covers actions and API routes)
198199
// 2. Wrap the default export with `withSentry` from @sentry/cloudflare for
@@ -215,6 +216,7 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
215216
// Ref: https://developers.cloudflare.com/workers/runtime-apis/nodejs/
216217
updateConfig({
217218
vite: {
219+
plugins: [sentryCloudflareNodeWarningPlugin()],
218220
ssr: {
219221
// @sentry/node is required in case we have 2 different @sentry/node
220222
// packages installed in the same project.
@@ -255,6 +257,41 @@ function findDefaultSdkInitFile(type: 'server' | 'client'): string | undefined {
255257
.find(filename => fs.existsSync(filename));
256258
}
257259

260+
/**
261+
* Detects if the project is a Cloudflare Pages project by checking for
262+
* `pages_build_output_dir` in the wrangler configuration file.
263+
*
264+
* Cloudflare Pages projects use `pages_build_output_dir` while Workers projects
265+
* use `assets.directory` or `main` fields instead.
266+
*/
267+
function isCloudflarePages(): boolean {
268+
const cwd = process.cwd();
269+
const configFiles = ['wrangler.jsonc', 'wrangler.json', 'wrangler.toml'];
270+
271+
for (const configFile of configFiles) {
272+
const configPath = path.join(cwd, configFile);
273+
274+
if (!fs.existsSync(configPath)) {
275+
continue;
276+
}
277+
278+
const content = fs.readFileSync(configPath, 'utf-8');
279+
280+
if (configFile.endsWith('.toml')) {
281+
// https://regex101.com/r/Uxe4p0/1
282+
// Match pages_build_output_dir as a TOML key (at start of line, ignoring whitespace)
283+
// This avoids false positives from comments (lines starting with #)
284+
return /^\s*pages_build_output_dir\s*=/m.test(content);
285+
}
286+
287+
// Match "pages_build_output_dir" as a JSON key (followed by :)
288+
// This works for both .json and .jsonc without needing to strip comments
289+
return /"pages_build_output_dir"\s*:/.test(content);
290+
}
291+
292+
return false;
293+
}
294+
258295
function getSourcemapsAssetsGlob(config: AstroConfig): string {
259296
// The vercel adapter puts the output into its .vercel directory
260297
// However, the way this adapter is written, the config.outDir value is update too late for

0 commit comments

Comments
 (0)