Repository: vercel/next.js
Pull request: [segment explorer] normalize path when running inside monorepo

When you running `pnpm next <project path>` from the monorepo root with turbopack and the `<project path>` is not same as your root directory, this lead the unrelated paths outside of the next.js project are also included into the segment explorer file paths. Because in turbopack the current directory is changed to `[project]` after bundling so that we didn't get the correct relative path when running segment explorer.

The absolute path is formatted as `<project-root>/<cwd>`,  and the `<project root>` will be included into the path if the working directory is not same as the next.js directory. The PR fixes the issue by extracting the `<project-root>` from the absolute path, and also stripped from the segment explorer paths.

Closes NEXT-4651

Changed files:
filename: packages/next/src/server/app-render/app-render.tsx
patch: @@ -4145,9 +4145,9 @@ const getGlobalErrorStyles = async (
   }
   if (ctx.renderOpts.dev) {
     const dir =
-      process.env.NEXT_RUNTIME === 'edge'
-        ? process.env.__NEXT_EDGE_PROJECT_DIR!
-        : ctx.renderOpts.dir || ''
+      (process.env.NEXT_RUNTIME === 'edge'
+        ? process.env.__NEXT_EDGE_PROJECT_DIR
+        : ctx.renderOpts.dir) || ''
 
     const globalErrorModulePath = normalizeConventionFilePath(
       dir,

filename: packages/next/src/server/app-render/create-component-tree.tsx
patch: @@ -417,9 +417,9 @@ async function createComponentTreeInternal(
     process.env.NODE_ENV === 'development' &&
     ctx.renderOpts.devtoolSegmentExplorer
   const dir =
-    process.env.NEXT_RUNTIME === 'edge'
-      ? process.env.__NEXT_EDGE_PROJECT_DIR!
-      : ctx.renderOpts.dir || ''
+    (process.env.NEXT_RUNTIME === 'edge'
+      ? process.env.__NEXT_EDGE_PROJECT_DIR
+      : ctx.renderOpts.dir) || ''
 
   // Use the same condition to render metadataOutlet as metadata
   const metadataOutlet = StreamingMetadataOutlet ? (
@@ -1139,9 +1139,9 @@ async function createBoundaryConventionElement({
     process.env.NODE_ENV === 'development' &&
     ctx.renderOpts.devtoolSegmentExplorer
   const dir =
-    process.env.NEXT_RUNTIME === 'edge'
-      ? process.env.__NEXT_EDGE_PROJECT_DIR!
-      : ctx.renderOpts.dir || ''
+    (process.env.NEXT_RUNTIME === 'edge'
+      ? process.env.__NEXT_EDGE_PROJECT_DIR
+      : ctx.renderOpts.dir) || ''
   const { SegmentViewNode } = ctx.componentMod
   const element = Component ? (
     <>

filename: packages/next/src/server/app-render/segment-explorer-path.ts
patch: @@ -9,11 +9,17 @@ export function normalizeConventionFilePath(
   projectDir: string,
   conventionPath: string | undefined
 ) {
+  // Turbopack project path is formed as: "<project root>/<cwd>".
+  // When project root is not the working directory, we can extract the relative project root path.
+  // This is mostly used for running Next.js inside a monorepo.
   const cwd = process.env.NEXT_RUNTIME === 'edge' ? '' : process.cwd()
+  const relativeProjectRoot = projectDir.replace(cwd, '')
 
   let relativePath = (conventionPath || '')
     // remove turbopack [project] prefix
-    .replace(/^\[project\][\\/]/, '')
+    .replace(/^\[project\]/, '')
+    // remove turbopack relative project path, everything after [project] and before the working directory.
+    .replace(relativeProjectRoot, '')
     // remove the project root from the path
     .replace(projectDir, '')
     // remove cwd prefix