# Cloudflare Wrangler Sourcemaps on Sentry 2025-06-22 I just spent way too much time figuring out how to get proper sourcemaps working for a Cloudflare Workers project that uses Sentry for error monitoring. The default Wrangler setup uses esbuild internally, and while you *can* get sourcemaps working with esbuild, Sentry's Vite plugin makes this trivially easy. ## The Problem Cloudflare Workers deployed via `wrangler deploy` use esbuild by default. This is fast and works great, but when errors happen in production, Sentry shows you minified stack traces that are basically useless: ``` Error: Something went wrong at a (index.js:1:234) at b (index.js:1:567) ``` Not helpful when you're trying to debug a production issue at 2am. ## The Solution Wrangler supports Vite as an alternative bundler, and Sentry has excellent Vite plugin support. Here's my complete config: **vite.config.ts:** ```typescript import { resolve } from "node:path"; import { cloudflare } from "@cloudflare/vite-plugin"; import { sentryVitePlugin } from "@sentry/vite-plugin"; import { defineConfig, loadEnv } from "vite"; export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ""); const envValue = env["NODE_ENV"] === "development" ? "development" : "production"; return { define: { __ENV__: JSON.stringify(envValue), }, resolve: { alias: { "~": resolve(__dirname, "./src"), }, }, plugins: [ cloudflare(), sentryVitePlugin({ org: process.env["SENTRY_ORG"] ?? "your-org", project: process.env["SENTRY_PROJECT"] ?? "api", authToken: process.env["SENTRY_AUTH_TOKEN"], debug: envValue === "development", sourcemaps: { assets: [".vite/your_worker/**/*.js", ".vite/your_worker/**/*.map"], }, }), ], build: { sourcemap: true, outDir: resolve(__dirname, "./.vite"), }, server: { port: 8787, host: "0.0.0.0", allowedHosts: true, }, }; }); ``` ## Injecting Build-Time Variables One nice feature of Vite is the `define` option, which lets you inject constants at build time. I use this for environment detection: ```typescript define: { __ENV__: JSON.stringify(envValue), } ``` Then in your worker code: ```typescript declare const __ENV__: string; ``` This gets replaced at build time, so there's no runtime overhead. Much cleaner than checking `process.env` or other runtime environment detection. ## Environment Variables Gotcha Here's something that tripped me up: Cloudflare Workers bindings (like secrets) don't work in CI environments. You can't use `wrangler secrets put SENTRY_AUTH_TOKEN` and expect it to be available during your build process. Instead, you need to set `SENTRY_AUTH_TOKEN` as a regular environment variable if you're using [Worker Builds](https://developers.cloudflare.com/workers/ci-cd/builds/$0). The Sentry auth token is only needed at build time for uploading sourcemaps - it's not a runtime dependency of your worker. ## Package Scripts **package.json:** ```json { "scripts": { "deploy": "vite build && wrangler deploy --outdir=.vite/your_worker", "dev": "vite dev" } } ``` **wrangler.jsonc** ```json { "name": "your-worker", "compatibility_date": "2025-06-17" "main": "./src/index.ts", } ``` ## What This Gets You 1. **Automatic sourcemap upload**: The Sentry Vite plugin handles uploading sourcemaps during build 2. **Proper stack traces**: Production errors now show actual function names and line numbers 3. **Release tracking**: Each deploy gets tagged with a release ID for better error correlation 4. **Build-time constants**: Use `define` to inject environment-specific values 5. **Hot reloading**: Development server with proper alias resolution ## The Critical Detail Make sure your `wrangler deploy --outdir` matches your Vite `build.outDir`. In my case, Vite outputs to `.vite/` and Wrangler deploys from `.vite/your_worker/`. This took me way too long to debug when they were mismatched. ## Development vs Production For development, `wrangler dev` automatically detects and uses your Vite config. For production, the two-step `vite build && wrangler deploy` ensures sourcemaps are generated and uploaded before the worker goes live. ## Sentry Integration with Release Tracking Here's how I wire up Sentry in the actual worker code to use the deployment metadata for release tracking: ```typescript interface Env { Variables: {}; Bindings: Readonly; } const app = new Hono(); app.get("/_error", () => { throw new Error(`😵‍💫 im an error on ${__ENV__}`); }); app.get("/_error/sentry", () => { Sentry.withScope((scope) => { scope.setExtra("foo", "bar"); Sentry.captureException(new Error("foobar")); }); return new Response("😖 im a sentry error"); }); const handler: ExportedHandler = { fetch: app.fetch, } export default Sentry.withSentry((env) => { const typedEnv = env; const { id: versionId } = typedEnv.CF_VERSION_METADATA; return { dsn: typedEnv.SENTRY_DSN, release: versionId, environment: __ENV__, sendDefaultPii: true, }; }, handler); ``` The magic here is `CF_VERSION_METADATA` - this gives you access to Cloudflare's deployment metadata, including a unique version ID for each deployment. This becomes your Sentry release ID, which links errors to specific deployments and sourcemaps. To enable this binding, add it to your `wrangler.jsonc`: ```json { "version_metadata": { "binding": "CF_VERSION_METADATA" } } ``` Now when errors occur, they're automatically tagged with the exact deployment version, making it easy to correlate issues with specific releases. ## The Complete Picture With this setup: 1. Vite builds your worker and generates sourcemaps 2. Sentry plugin uploads sourcemaps tagged with version metadata 3. Wrangler deploys with the version metadata binding 4. Runtime errors get tagged with the deployment version 5. Sentry shows proper stack traces with source file/line numbers This setup has made debugging production issues so much easier. No more guessing which minified function threw an error. The combination of Vite's modern tooling and Sentry's excellent plugin support really does make a difference. ## Useful Resources - [Cloudflare Vite Plugin](https://github.com/cloudflare/workers-sdk/tree/main/packages/vite-plugin) - Official Vite plugin for Cloudflare Workers - [Sentry Vite Plugin](https://docs.sentry.io/platforms/javascript/sourcemaps/uploading/vite/) - Documentation for Sentry's Vite integration - [Sentry Cloudflare Integration](https://docs.sentry.io/platforms/javascript/guides/cloudflare-workers/) - Setting up Sentry with Cloudflare Workers