Skip to content
This repository has been archived by the owner on Jul 31, 2024. It is now read-only.

Support for Next 13 App Folder and Root Layout #154

Closed
aylton-almeida opened this issue Aug 18, 2023 · 16 comments · Fixed by #176
Closed

Support for Next 13 App Folder and Root Layout #154

aylton-almeida opened this issue Aug 18, 2023 · 16 comments · Fixed by #176

Comments

@aylton-almeida
Copy link

Is your feature request related to a problem? Please describe.

I'm creating a new Next JS App using the App Folder and I wanted to know if support for it and the Root Layout config already exists. I suppose I would need to add the beforeTimingHeader logic directly into the layout.tsx file, but when trying implement it and run I receive errors about not having being able to resolve some dependencies while import newrelic. I suppose this may happen because of client vs server side rendering, but I'm not so sure.

Feature Description

Support for Next 13s App folder

Describe Alternatives

N/A

Additional context

Here are both my layout.tsx file and the error logs I receive when accessing the site locally.

image

Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/@newrelic/native-metrics/lib/pre-build.js
./node_modules/@newrelic/native-metrics/index.js
./node_modules/newrelic/lib/sampler.js
./node_modules/newrelic/lib/agent.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/@newrelic/native-metrics/lib/pre-build.js
Module not found: Can't resolve 'node-gyp' in '<hidden>/node_modules/@newrelic/native-metrics/lib'

Import trace for requested module:
./node_modules/@newrelic/native-metrics/lib/pre-build.js
./node_modules/@newrelic/native-metrics/index.js
./node_modules/newrelic/lib/sampler.js
./node_modules/newrelic/lib/agent.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/@newrelic/native-metrics/lib/pre-build.js
Module not found: Can't resolve 'npm' in '<hidden>/node_modules/@newrelic/native-metrics/lib'

Import trace for requested module:
./node_modules/@newrelic/native-metrics/lib/pre-build.js
./node_modules/@newrelic/native-metrics/index.js
./node_modules/newrelic/lib/sampler.js
./node_modules/newrelic/lib/agent.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/@newrelic/security-agent/lib/instrumentation-security/core/sec-utils.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/@newrelic/security-agent/lib/instrumentation-security/core/sec-utils.js
./node_modules/@newrelic/security-agent/lib/instrumentation-security/hooks/native/nr-childProcess.js
./node_modules/@newrelic/security-agent/lib/instrumentation-security/index.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/index.js
./node_modules/@newrelic/security-agent/index.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/applicationinfo.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/applicationinfo.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/index.js
./node_modules/@newrelic/security-agent/index.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/log4js/lib/appenders/index.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/log4js/lib/appenders/index.js
./node_modules/log4js/lib/log4js.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/logging.js
./node_modules/@newrelic/security-agent/lib/nr-security-api/index.js
./node_modules/@newrelic/security-agent/index.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/log4js/lib/appenders/index.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/log4js/lib/appenders/index.js
./node_modules/log4js/lib/log4js.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/logging.js
./node_modules/@newrelic/security-agent/lib/nr-security-api/index.js
./node_modules/@newrelic/security-agent/index.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/newrelic/api.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/newrelic/api.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/newrelic/lib/config/index.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/newrelic/lib/config/index.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/newrelic/lib/proxy/grpc.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/newrelic/lib/proxy/grpc.js
./node_modules/newrelic/lib/grpc/connection.js
./node_modules/newrelic/lib/spans/create-span-event-aggregator.js
./node_modules/newrelic/lib/agent.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/newrelic/lib/shim/shim.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/newrelic/lib/shim/shim.js
./node_modules/newrelic/lib/shim/transaction-shim.js
./node_modules/newrelic/api.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/newrelic/lib/shimmer.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/newrelic/lib/shimmer.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/newrelic/lib/shimmer.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/newrelic/lib/shimmer.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/newrelic/lib/shimmer.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/newrelic/lib/shimmer.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/sync-rpc/lib/worker.js
Critical dependency: the request of a dependency is an expression

Import trace for requested module:
./node_modules/sync-rpc/lib/worker.js
./node_modules/sync-rpc/lib/index.js
./node_modules/sync-request/lib/index.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/applicationinfo.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/index.js
./node_modules/@newrelic/security-agent/index.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/ws/lib/buffer-util.js
Module not found: Can't resolve 'bufferutil' in '<hidden>/node_modules/ws/lib'

Import trace for requested module:
./node_modules/ws/lib/buffer-util.js
./node_modules/ws/lib/websocket.js
./node_modules/ws/index.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/connections/websocket/websocket.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/connections/websocket/index.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/websocket-client.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/index.js
./node_modules/@newrelic/security-agent/index.js
./node_modules/newrelic/index.js
./app/layout.tsx

./node_modules/ws/lib/validation.js
Module not found: Can't resolve 'utf-8-validate' in '<hidden>/node_modules/ws/lib'

Import trace for requested module:
./node_modules/ws/lib/validation.js
./node_modules/ws/lib/receiver.js
./node_modules/ws/index.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/connections/websocket/websocket.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/connections/websocket/index.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/lib/core/websocket-client.js
./node_modules/@newrelic/security-agent/lib/nr-security-agent/index.js
./node_modules/@newrelic/security-agent/index.js
./node_modules/newrelic/index.js
./app/layout.tsx

Priority

For me this is a Blocker since I can't use newrelic with my app

@workato-integration
Copy link

@bizob2828 bizob2828 self-assigned this Sep 18, 2023
@TomasGonzalez
Copy link

I'm also having this issue. any workaround?

@pyleglise
Copy link

Hi there !
I have a similar problem.
I could make it work with pages router architecture but not in App router...

@pyleglise
Copy link

pyleglise commented Oct 21, 2023

Hi there ! I have a similar problem. I could make it work with pages router architecture but not in App router...

Ok, I finally succeded !
Here's how I did :

./app/layout.js :

/*   your imports  */
import NewRelicSnippet from '../components/newrelicSnippet'  // a new React component you will create next step.
export default function RootLayout({ children }) {
  return (
    <>
      <html lang="en">
        <head>
          <NewRelicSnippet /> // a new React component you will create next step.
        </head>
       
        <body>
        // your code...
        </body>
      </html>
    </>
  )
}

You will have to go to Newrelic web site and copy/paste the javascript part of the snippet, in the settings of your app (Browser section).
But be carefull : you will have to find/replace the 4 '\n' with space in the javascript snippet code.

Then create you snippet React component :

../components/newrelicSnippet.jsx :

const snippet = `;window.NREUM||.... paste your snippet but REPLACE \n WITH SPACE !!!! <=this is the key`
const NewRelicSnippet = () => {
  
  return (
    <>
      <meta httpEquiv="x-ua-compatible" content="ie=edge"></meta>
      <script
        id="newrelic"
        type="text/javascript"
        dangerouslySetInnerHTML={{ __html: snippet }}
      ></script>
    </>
  )
}
export default NewRelicSnippet

And that worked for me.
Not very clean, I agree, but it works !

@agwermann
Copy link

@bizob2828 is there some fix for this issue? The workaround provided by @pyleglise works, but in my scenario, it is not so feasible, since this must be applied to tens of apps deployed to different environments/different new relic accounts.

@bizob2828 bizob2828 removed their assignment Oct 30, 2023
@TomasGonzalez
Copy link

TomasGonzalez commented Nov 6, 2023

I'm not getting logs from Pino with this approach. Although other things are working like traces and JS errors.

@kalm42
Copy link

kalm42 commented Nov 15, 2023

There's probably a better way to do this and if there is please tell me. I wanted to try @pyleglise 's suggested solution but I didn't have the snippet itself because all the guides instruct you to get the snippet via the newrelic.getBrowserTimingHeader() method. To complicate things we're all in on the app directory.

So I did the following to obtain the snippet code.

  1. Created the _document.tsx file straight copied from here.
  2. Added a random page to the page directory.
  3. Went to the page and copied the snippet out of the dom.

It works. It's hacky. I hope the snippet doesn't change from time to time. But it works. Now please tell me how wrong I am.

@samkit5495
Copy link

I was able to resolve this by adding the following to next.config.js

module.exports = {
  experimental: {
    serverComponentsExternalPackages: ["newrelic"],
  },
};

Reference: vercel/next.js#52876

@fmacherey
Copy link

Are there any updates on this topic?

I got it working, but still seeing the errors while yarn build in my next application. I added to config in next.config.js as @samkit5495 described above, and integrated the browser timing header, in the RootLayout:

 // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
const newrelic = require("newrelic");
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
const browserTimingHeader = newrelic.getBrowserTimingHeader({
    hasToRemoveScriptWrapper: true,
});
// ... in return:
<Script
    id="newrelic-browser-timing-header"
    type="text/javascript"
    dangerouslySetInnerHTML={{
        /* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */
        __html: browserTimingHeader,
    }}
/>

@kalm42
Copy link

kalm42 commented Nov 17, 2023

I was able to resolve this by adding the following to next.config.js

module.exports = {
  experimental: {
    serverComponentsExternalPackages: ["newrelic"],
  },
};

Reference: vercel/next.js#52876

This is what worked for me.

Relevant dependencies

	"dependencies": {
		"newrelic": "11.5.0",
		"next": "13.5.1",
		"react": "18.2.0",
		"react-dom": "18.2.0",
	},
	"devDependencies": {
		"@types/newrelic": "9.14.3",

node: v18.16.0
npm: 9.5.1

@rafbgarcia
Copy link

Did anyone face this error?

Error: newrelic__WEBPACK_IMPORTED_MODULE_10__.getBrowserTimingHeader is not a function

@bizob2828
Copy link
Member

I'm not following what the actual issue is here. I added a PR to officially test an application written in the App Router style. It seems like the request is trying to figure out how to inject the browser agent, which this package doesn't automatically do. I do see this comment explaining how to fix it here. It might also be worth checking out #175 regarding the comment @TomasGonzalez posted. I will keep this open a few more days but we support App Router already with 0 changes

@tclass
Copy link

tclass commented Mar 12, 2024

I was able to resolve this by adding the following to next.config.js

module.exports = {
  experimental: {
    serverComponentsExternalPackages: ["newrelic"],
  },
};

Reference: vercel/next.js#52876

@kalm42 so you're adding that and what else do you need to do?

@bizob2828
Copy link
Member

bizob2828 commented Mar 12, 2024

@tclass I think that reference is a way to tell next.js and subsequently webpack to exterrnalize the newrelic module if you are requiring it within your next.js app. This should only be needed if you're trying to get the browser agent via newrelic.getBrowserTimingHeader. If you don't need the browser agent, you can skip that update to next.config.js as we recommend loading the next.js instrumentation via NODE_OPTIONS='-r @newrelic/next' next start

@bizob2828
Copy link
Member

This is a duplicate of #173. We have added a test app with app router and shows no issues with instrumentation. We also plan to follow up with better example applications and documentation around injecting browser agent

@missniu
Copy link

missniu commented Apr 25, 2024

Hi there !
I have a similar problem.
I use App router and client component...

@bizob2828 bizob2828 moved this to Done: Issues recently completed in Node.js Engineering Board Jul 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.