|
| 1 | +## Exceptionless for Next.js |
| 2 | + |
| 3 | +This example is a very small App Router site that shows the Exceptionless integration shape we want for a Next.js app: simple setup, rich metadata, and clear client/server error coverage. |
| 4 | + |
| 5 | +- `instrumentation-client.js` for browser startup and navigation logging |
| 6 | +- `instrumentation.js` for server startup and `onRequestError` |
| 7 | +- `app/error.jsx` for route-level client render failures |
| 8 | +- `app/global-error.jsx` for root-level client render failures |
| 9 | +- `app/api/demo/route.js` for explicit server-side logging from a route handler |
| 10 | + |
| 11 | +### What it covers |
| 12 | + |
| 13 | +- Manual client logs with structured data |
| 14 | +- Handled client exceptions submitted from a `try`/`catch` |
| 15 | +- Unhandled client promise rejections captured by the browser global handler |
| 16 | +- A client transition crash that lands in `app/error.jsx` |
| 17 | +- A server route log enriched with request headers, IP, path, query string, and JSON body |
| 18 | +- An unhandled route handler error captured by `onRequestError` |
| 19 | +- A server component render error captured by `onRequestError` |
| 20 | + |
| 21 | +### Why it is shaped this way |
| 22 | + |
| 23 | +This sticks to the native Next.js file boundaries instead of inventing another framework layer: |
| 24 | + |
| 25 | +- `instrumentation-client.js` is where client-side monitoring starts before the app becomes interactive. |
| 26 | +- `instrumentation.js` and `onRequestError` are where uncaught server render, route handler, server action, and proxy errors are captured. |
| 27 | +- `app/error.jsx` and `app/global-error.jsx` stay responsible for client render failures inside the App Router. |
| 28 | +- Route handlers submit logs directly with `Exceptionless.createLog(...)`, the environment module memoizes `Exceptionless.startup(...)`, and the server flushes with `Exceptionless.processQueue()` when needed. |
| 29 | + |
| 30 | +### Vercel-specific notes |
| 31 | + |
| 32 | +- The server helper flushes the Exceptionless queue explicitly. That matters for short-lived serverless runtimes where a background timer may not get enough time to send queued events. |
| 33 | +- The route handler uses `after()` so normal server logs flush after the response is sent. |
| 34 | +- The example locally aliases `source-map` to `false` in `next.config.mjs` so an unused `stacktrace-gps` AMD branch does not leak a `source-map` dependency into `@exceptionless/browser`. |
| 35 | +- The helper files import the built ESM bundles from `packages/browser/dist/index.bundle.js` and `packages/node/dist/index.bundle.js` because the package entrypoints still re-export internal `#/*` imports. The example also uses `--webpack` because Turbopack currently rejects the node bundle during page data collection on `node-localstorage`'s dynamic `require`. |
| 36 | +- If we later package this for production ergonomics, the clean split is likely a very thin `@exceptionless/nextjs` helper for framework hooks plus an optional `@exceptionless/vercel` add-on for `@vercel/otel`, deployment metadata, and queue-flush helpers. |
| 37 | + |
| 38 | +### Environment variables |
| 39 | + |
| 40 | +Set the env vars you want the example to use: |
| 41 | + |
| 42 | +- `NEXT_PUBLIC_EXCEPTIONLESS_API_KEY` |
| 43 | +- `NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL` |
| 44 | +- `EXCEPTIONLESS_API_KEY` |
| 45 | +- `EXCEPTIONLESS_SERVER_URL` |
| 46 | + |
| 47 | +### Run locally |
| 48 | + |
| 49 | +1. `npm install` |
| 50 | +2. `npm run build` |
| 51 | +3. `cd example/nextjs` |
| 52 | +4. `npm run dev` |
0 commit comments