Next.js is a powerful JavaScript framework that offers optimized speed and performance for both development and runtime. With the release of Next.js 13, the App Router has become the recommended way to handle routing in Next.js applications. This new router leverages React’s latest features, such as Server Components and Streaming, to offer a more modern and efficient approach to building web applications.
In this blog post, you’ll learn how to set up application performance monitoring for the server side and browser monitoring for the frontend using the new App Router, giving you full-stack observability in your Next.js application. To start, you’ll need a New Relic account and license key, both available for free.
For more information on monitoring Next.js applications using the Pages Router, check out our previous article
Installing the agent
Run the following command in your Next.js project to install the New Relic Node.js (APM) agent.
npm install newrelic
After the command completes successfully, you’ll see the dependencies included in your package.json
file.
"dependencies": {
"newrelic": "^12.3.0",
"next": "14.2.5",
"react": "^18",
"react-dom": "^18"
},
As of version 12.0.0 of the New Relic Node.js agent, the @newrelic/next package is now included by default, eliminating the need for a separate installation. This built-in support provides official instrumentation for monitoring Next.js applications, focusing on server-side rendering, middleware, and transaction naming for both page and server requests. This ensures comprehensive observability of server-side activities.
The integration with the New Relic Node.js agent offers all the agent's capabilities, enhancing performance monitoring and error tracking in Next.js applications.
While it doesn't cover client-side actions, you can inject the New Relic browser agent for client-side telemetry (more on that later in this blog post).
Configuration
To effectively instrument a Next.js application with New Relic, you need to modify the next.config.js
file. This configuration ensures that the modules supported by New Relic are not mangled by webpack, and it externalizes those modules.
Create or update the next.config.js
file in your project root with the following content:
'use strict'
const nrExternals = require('newrelic/load-externals')
module.exports = {
experimental: {
serverComponentsExternalPackages: ['newrelic']
},
webpack: (config) => {
nrExternals(config)
return config
}
}
Next, modify your dev
and start
npm scripts by amending the scripts
section of package.json
file. Allow your application to run with Node’s -r
option, which will preload newrelic
module.
"scripts": {
"dev": "NODE_OPTIONS='-r newrelic' next",
"build": "next build",
"start": "NODE_OPTIONS='-r newrelic' next start",
"lint": "next lint"
}
Before you run your application, add the newrelic.js
AMP agent configuration file to the root directory of your project. For more information, see an example config file for your Next.js app.
Additionally, use NEW_RELIC_APP_NAME
and NEW_RELIC_LICENSE_KEY
in your .env
file as shown in an example .env file for your application.
Viewing performance data in New Relic
Run your application and go to the APM page in New Relic. You’ll see your application’s server-side data flowing into New Relic.
Frontend observability
To inject the browser agent when using the App Router, we’ll be editing the app/layout.js(.ts) file.
import Script from 'next/script'
import Link from 'next/link'
import newrelic from 'newrelic'
import './style.css'
export default async function RootLayout({ children }) {
if (newrelic.agent.collector.isConnected() === false) {
await new Promise((resolve) => {
newrelic.agent.on("connected", resolve)
})
}
const browserTimingHeader = newrelic.getBrowserTimingHeader({
hasToRemoveScriptWrapper: true,
allowTransactionlessInjection: true,
})
return (
<html>
<Script
id="nr-browser-agent"
dangerouslySetInnerHTML={{ __html: browserTimingHeader }}
/>
<body>
<ul className="navbar">
<li><a href="/">Home</a></li>
<li><Link href="/users" key={"users"}>Users</Link></li>
<li><Link href="/about" key={"about"}>About</Link></li>
</ul>
{children}
</body>
</html>
)
}
Here are the steps for this process:
- Install the
newrelic
npm package if you haven’t already with thenpm install newrelic
command. - Add the
newrelic.getBrowserTimingHeader
method.- Pass
hasToRemoveScriptWrapper: true
as an argument tonewrelic.getBrowserTimingHeader
so that the browser script is returned without the<script>
wrapper. See the node-newrelic docs for more details. - Pass
allowTransactionlessInjection: true
as an argument tonewrelic.GetBrowserTimingHeader
to allow injection of the browser agent when not in a transaction.
- Pass
- In the render method, inject the New Relic Browser agent script to the end of the
<body>
of the document. - The
layout.js(.ts)
file should be in the root of the app directory of your project.
For the example layout.js(.ts)
file, visit the following link.
Viewing browser data in New Relic
Start the application and then go to the browser monitoring page in New Relic to see client-side data from your application flowing into New Relic.
Sending detailed error information to New Relic
For capturing detailed error information in your Next.js application, you need to handle both client-side and server-side errors.
Client-side errors
For client-side errors, you can use the error.ts(.js)
file to capture and send error details to New Relic. Below is an example of how this can be implemented:
"use client";
import React, { useEffect } from "react";
const Error = ({ error }) => {
useEffect(() => {
if (window.newrelic) {
window.newrelic.noticeError(error);
}
}, [error]);
return <div>Something went wrong</div>;
};
export default Error;
In this example, the useEffect
hook is used to call window.newrelic.noticeError
whenever an error occurs. This sends the error details to New Relic for further analysis.
error.js(.ts)
file defines an error UI boundary for a route segment. To handle errors in root layout, use global-error.js(.ts)
and place it in the root app
directory.
For more information on error handling in Next.js, refer to the Next.js documentation.
Server-side errors
For errors coming from the backend, the newrelic
module handles them out of the box. You don't need to add any additional code for server-side error tracking; the module will automatically capture and report these errors to New Relic.
This ensures that both client-side and server-side errors are effectively monitored and reported to New Relic, providing comprehensive error tracking for your Next.js application.
Next steps
- You can find all the code samples in this blog post in the newrelic-node-examples GitHub repository. You can give us any feedback in the GitHub repository issues section.
- Check out our Next.js integration page on GitHub.
- Sign up for a free New Relic account. Your free account includes 100 GB/month of free data ingest, one free full-access user, and unlimited free basic users.
The views expressed on this blog are those of the author and do not necessarily reflect the views of New Relic. Any solutions offered by the author are environment-specific and not part of the commercial solutions or support offered by New Relic. Please join us exclusively at the Explorers Hub (discuss.newrelic.com) for questions and support related to this blog post. This blog may contain links to content on third-party sites. By providing such links, New Relic does not adopt, guarantee, approve or endorse the information, views or products available on such sites.