Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App router migration new relic configuration #1

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { Metadata } from 'next';
import { newRelicInit } from '../config/newRelic';

// Nextjs automatically includes for each route two default meta tags, charset and viewport
// https://nextjs.org/docs/app/building-your-application/optimizing/metadata#default-fields
export const metadata: Metadata = {
title: 'Bloom',
};

export default function RootLayout({
export default async function RootLayout({
// Layouts must accept a children prop.
// This will be populated with nested layouts or pages
children,
}: {
children: React.ReactNode;
}) {
const NewRelicScript = await newRelicInit();
return (
<html lang="en">
<body>{children}</body>
<body>
{children}
{NewRelicScript}
</body>
</html>
);
}
46 changes: 46 additions & 0 deletions config/newRelic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import newrelic from 'newrelic';
import Script from 'next/script';

// Configuration according to Newrelic app router example
// See https://github.com/newrelic/newrelic-node-nextjs?tab=readme-ov-file#example-projects
export const newRelicInit = async () => {
// @ts-ignore
if (newrelic.agent.collector.isConnected() === false) {
await new Promise((resolve) => {
// @ts-ignore
newrelic.agent.on('connected', resolve);
});
}

const browserTimingHeader = newrelic.getBrowserTimingHeader({
hasToRemoveScriptWrapper: true,
// @ts-ignore
allowTransactionlessInjection: true,
});

return <NewRelicScript browserTimingHeader={browserTimingHeader} />;
};

export type NewRelicScriptProps = {
browserTimingHeader: string;
};

const NewRelicScript = ({ browserTimingHeader }: NewRelicScriptProps) => {
return (
// eslint-disable-next-line @next/next/no-before-interactive-script-outside-document
<Script
// We have to set an id for inline scripts.
// See https://nextjs.org/docs/app/building-your-application/optimizing/scripts#inline-scripts
id="nr-browser-agent"
// By setting the strategy to "beforeInteractive" we guarantee that
// the script will be added to the document's `head` element.
strategy="beforeInteractive"
// The body of the script element comes from the async evaluation
// of `getInitialProps`. We use the special
// `dangerouslySetInnerHTML` to provide that element body. Since
// it requires an object with an `__html` property, we pass in an
// object literal.
dangerouslySetInnerHTML={{ __html: browserTimingHeader }}
/>
);
};
18 changes: 18 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,26 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});

// Configuration according to Newrelic app router example
// See https://github.com/newrelic/newrelic-node-nextjs?tab=readme-ov-file#example-projects
const nrExternals = require('@newrelic/next/load-externals');

module.exports = withBundleAnalyzer(
withPWA({
experimental: {
// Without this setting, the Next.js compilation step will routinely
// try to import files such as `LICENSE` from the `newrelic` module.
// See https://nextjs.org/docs/app/api-reference/next-config-js/serverComponentsExternalPackages.
serverComponentsExternalPackages: ['newrelic'],
},

// In order for newrelic to effectively instrument a Next.js application,
// the modules that newrelic supports should not be mangled by webpack. Thus,
// we need to "externalize" all of the modules that newrelic supports.
webpack: (config) => {
nrExternals(config);
return config;
},
reactStrictMode: true,
publicRuntimeConfig: {
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
Expand Down
Loading