Next.js Walkthrough
Overview
Our Next.js SDK gives you access to frontend session replays and server-side monitoring, all-in-one.
- On the frontend, the
<HighlightInit/>component sets up client-side session replays.
- On the backend, the
withHighlightwrapper captures server-side errors and logs from your API.
- The
withHighlightConfigconfiguration wrapper automatically proxies highlight data to bypass ad-blockers and uploads source maps so your frontend errors include stack traces to your source code.
Installation
# with yarn yarn add @highlight-run/next @highlight-run/react highlight.run
Client Instrumentation
This implementation requires React 17 or greater. If you're behind on React versions, follow our React.js docs
- For the
/pagesdirectory, you'll want to addHighlightInitto_app.tsx.
// pages/_app.tsx import { AppProps } from 'next/app' import CONSTANTS from '@/app/constants' import { HighlightInit } from '@highlight-run/next/highlight-init' export default function MyApp({ Component, pageProps }: AppProps) { return ( <> <HighlightInit projectId={CONSTANTS.NEXT_PUBLIC_HIGHLIGHT_PROJECT_ID} tracingOrigins networkRecording={{ enabled: true, recordHeadersAndBody: true }} backendUrl={CONSTANTS.NEXT_PUBLIC_HIGHLIGHT_BACKEND_URL} /> <Component {...pageProps} /> </> ) }
- For Next.js 13 App Directory, add
HighlightInitto yourlayout.tsxfile.
// src/app/layout.tsx import './globals.css' import CONSTANTS from '@/app/constants' import { HighlightInit } from '@highlight-run/next/highlight-init' export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <> <HighlightInit projectId={CONSTANTS.NEXT_PUBLIC_HIGHLIGHT_PROJECT_ID} tracingOrigins networkRecording={{ enabled: true, recordHeadersAndBody: true }} backendUrl={CONSTANTS.NEXT_PUBLIC_HIGHLIGHT_BACKEND_URL} /> <html lang="en"> <body>{children}</body> </html> </> ) }
API Route Instrumentation
- Create a file to export your
Highlightwrapper function:
// src/app/utils/highlight.config.ts: import CONSTANTS from '@/app/constants' import { Highlight } from '@highlight-run/next' export const withHighlight = Highlight({ projectID: '<YOUR_PROJECT_ID>', })
- Wrap your
/pages/apifunctions withwithHighlight:
// pages/api/test.ts import { NextApiRequest, NextApiResponse } from 'next' import { withHighlight } from '@/app/utils/highlight.config' export default withHighlight(function handler( req: NextApiRequest, res: NextApiResponse, ) { console.info('Here: /api/app-directory-test', { success }) if (Math.random() < 0.8) { res.send('Success: /api/app-directory-test') } else { throw new Error('Error: /api/app-directory-test') } })
Server Instrumentation
Excluding the Vercel edge runtime (which is a work in progress), Session Replay, Vercel Log Drain and Error Monitoring are fully operational for Next.js 13 App Directory
Next.js comes out of the box instrumented for Open Telemetry. Our example Highlight implementation will use Next's experimental instrumentation feature to configure Open Telemetry on our Next.js server. There are probably other ways to configure Open Telemetry with Next, but this is our favorite.
Adding the withHighlightConfig to your next config will configure highlight frontend proxying. This means that frontend session recording and error capture data will be piped through your domain on /highlight-events to avoid ad-blockers from stopping this traffic.
- Install
next-build-idwithnpm install next-build-id.
- Turn on
instrumentationHook.
- Wrap the config with
withHighlightConfig.
If you use a next.config.js file:
// next.config.js const nextBuildId = require('next-build-id') const { withHighlightConfig } = require('@highlight-run/next') /** @type {import('next').NextConfig} */ const nextConfig = { generateBuildId: () => nextBuildId({ dir: __dirname }), experimental: { appDir: true, instrumentationHook: true, }, productionBrowserSourceMaps: true, } module.exports = withHighlightConfig(nextConfig)
If you use a next.config.mjs file:
// next.config.mjs import { dirname } from 'path' import { fileURLToPath } from 'url' import nextBuildId from 'next-build-id' import { withHighlightConfig } from '@highlight-run/next' const __filename = fileURLToPath(import.meta.url) const __dirname = dirname(__filename) /** @type {import('next').NextConfig} */ const nextConfig = withHighlightConfig({ generateBuildId: () => nextBuildId({ dir: __dirname }), experimental: { appDir: true, instrumentationHook: true, }, productionBrowserSourceMaps: true, }) export default nextConfig
- Create
instrumentation.tsat the root of your project as explained in the instrumentation guide. CallregisterHighlightfrom within the exportedregisterfunction:
// instrumentation.ts import CONSTANTS from '@/app/constants' export async function register() { if (process.env.NEXT_RUNTIME === 'nodejs') { /** Conditional import required for use with Next middleware to avoid a webpack error * https://nextjs.org/docs/pages/building-your-application/routing/middleware */ const { registerHighlight } = await import('@highlight-run/next') registerHighlight({ projectID: CONSTANTS.NEXT_PUBLIC_HIGHLIGHT_PROJECT_ID, }) } }
- If you're using the App Router, copy
instrumentation.tstosrc/instrumentation.ts. See this Next.js discussion regardinginstrumentation.tswith App Router. You could also simply export theregisterfunction frominstrumentation.tsinsrc/instrumentation.tslike so:
// src/instrumentation.ts: export { register } from '../instrumentation'
Configure inlineImages
We use a package called rrweb to record web sessions. rrweb supports inlining images into sessions to improve replay accuracy, so that images that are only available from your local network can be saved; however, the inlined images can cause CORS issues in some situations.
We currently default inlineImages to true on localhost. Explicitly set inlineImages={false} if you run into trouble loading images on your page while Highlight is running. This will degrade tracking on localhost and other domains that are inaccessible to app.highlight.io.
Configure tracingOrigins and networkRecording
See Fullstack Mapping for details.
You likely want to associate your back-end errors to client sessions.
Source Map Validation
Source maps work differently in development mode than in production. Run
yarn build && yarn startto test compiled source maps in Highlight.
We recommend shipping your source maps to your production server. Your client-side JavaScript is always public, and code decompilation tools are so powerful that obscuring your source code may not be helpful.
Shipping source maps to production with Next.js is as easy as setting productionBrowserSourceMaps: true in your nextConfig. Alternatively, you can upload source maps directly to Highlight using our withHighlightConfig function.
Make sure to implement nextConfig.generateBuildId so that our source map uploader can version your source maps correctly.
// next.config.js const nextBuildId = require('next-build-id') const { withHighlightConfig } = require('@highlight-run/next') /** @type {import('next').NextConfig} */ const nextConfig = { generateBuildId: () => nextBuildId({ dir: __dirname }), experimental: { appDir: true, instrumentationHook: true, }, productionBrowserSourceMaps: false } module.exports = withHighlightConfig(nextConfig)
You must export your HIGHLIGHT_SOURCEMAP_UPLOAD_API_KEY to your build process. If you're building and deploying with Vercel, try our Highlight Vercel Integration to inject HIGHLIGHT_SOURCEMAP_UPLOAD_API_KEY automatically.
Vercel Log Drain
Vercel Log Drain works great. Install our Vercel + Highlight Integration to enable it.