Skip to content

Commit 5771ce1

Browse files
authored
[segment explorer] handle builtin not-found (#80607)
1 parent 7fea36c commit 5771ce1

File tree

6 files changed

+90
-52
lines changed

6 files changed

+90
-52
lines changed

packages/next/src/build/webpack/loaders/next-app-loader/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ const GLOBAL_NOT_FOUND_FILE_TYPE = 'global-not-found'
7979
const PAGE_SEGMENT = 'page$'
8080
const PARALLEL_CHILDREN_SEGMENT = 'children$'
8181

82-
const defaultGlobalErrorPath = 'next/dist/client/components/global-error'
83-
const defaultNotFoundPath = 'next/dist/client/components/not-found-error'
84-
const defaultLayoutPath = 'next/dist/client/components/default-layout'
85-
const defaultGlobalNotFoundPath = 'next/dist/client/components/global-not-found'
82+
const defaultGlobalErrorPath = 'next/dist/client/components/global-error.js'
83+
const defaultNotFoundPath = 'next/dist/client/components/not-found-error.js'
84+
const defaultLayoutPath = 'next/dist/client/components/default-layout.js'
85+
const defaultGlobalNotFoundPath =
86+
'next/dist/client/components/global-not-found.js'
8687

8788
type DirResolver = (pathToResolve: string) => string
8889
type PathResolver = (

packages/next/src/next-devtools/dev-overlay/components/overview/segment-explorer.tsx

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ function PageSegmentTreeLayerPresentation({
3939
node: SegmentTrieNode
4040
level: number
4141
}) {
42-
const nodeName = node.value?.type
4342
const childrenKeys = Object.keys(node.children)
4443

4544
const sortedChildrenKeys = childrenKeys.sort((a, b) => {
@@ -107,42 +106,38 @@ function PageSegmentTreeLayerPresentation({
107106
...{ paddingLeft: `${(level + 1) * 8}px` },
108107
}}
109108
>
110-
<div className="segment-explorer-line">
111-
<div className={`segment-explorer-line-text-${nodeName}`}>
112-
<div className="segment-explorer-filename">
113-
{folderName && (
114-
<span className="segment-explorer-filename--path">
115-
{folderName}
116-
{/* hidden slashes for testing snapshots */}
117-
<small>{'/'}</small>
118-
</span>
119-
)}
120-
{/* display all the file segments in this level */}
121-
{filesChildrenKeys.length > 0 && (
122-
<span className="segment-explorer-files">
123-
{filesChildrenKeys.map((fileChildSegment) => {
124-
const childNode = node.children[fileChildSegment]
125-
if (!childNode || !childNode.value) {
126-
return null
127-
}
128-
const fileName =
129-
childNode.value.pagePath.split('/').pop() || ''
130-
return (
131-
<span
132-
key={fileChildSegment}
133-
className={cx(
134-
'segment-explorer-file-label',
135-
`segment-explorer-file-label--${childNode.value.type}`
136-
)}
137-
>
138-
{fileName}
139-
</span>
140-
)
141-
})}
142-
</span>
143-
)}
144-
</div>
145-
</div>
109+
<div className="segment-explorer-filename">
110+
{folderName && (
111+
<span className="segment-explorer-filename--path">
112+
{folderName}
113+
{/* hidden slashes for testing snapshots */}
114+
<small>{'/'}</small>
115+
</span>
116+
)}
117+
{/* display all the file segments in this level */}
118+
{filesChildrenKeys.length > 0 && (
119+
<span className="segment-explorer-files">
120+
{filesChildrenKeys.map((fileChildSegment) => {
121+
const childNode = node.children[fileChildSegment]
122+
if (!childNode || !childNode.value) {
123+
return null
124+
}
125+
const fileName =
126+
childNode.value.pagePath.split('/').pop() || ''
127+
return (
128+
<span
129+
key={fileChildSegment}
130+
className={cx(
131+
'segment-explorer-file-label',
132+
`segment-explorer-file-label--${childNode.value.type}`
133+
)}
134+
>
135+
{fileName}
136+
</span>
137+
)
138+
})}
139+
</span>
140+
)}
146141
</div>
147142
</div>
148143
</div>
@@ -190,7 +185,6 @@ export function SegmentsExplorer({
190185

191186
export const DEV_TOOLS_INFO_RENDER_FILES_STYLES = css`
192187
.segment-explorer-content {
193-
overflow-y: auto;
194188
font-size: var(--size-14);
195189
margin: -12px -8px;
196190
}
@@ -210,6 +204,9 @@ export const DEV_TOOLS_INFO_RENDER_FILES_STYLES = css`
210204
padding-top: 10px;
211205
padding-bottom: 10px;
212206
padding-right: 4px;
207+
white-space: pre;
208+
cursor: default;
209+
color: var(--color-gray-1000);
213210
}
214211
215212
.segment-explorer-children--intended {
@@ -232,15 +229,6 @@ export const DEV_TOOLS_INFO_RENDER_FILES_STYLES = css`
232229
color: var(--color-gray-800);
233230
}
234231
235-
.segment-explorer-line {
236-
white-space: pre;
237-
cursor: default;
238-
}
239-
240-
.segment-explorer-line {
241-
color: var(--color-gray-1000);
242-
}
243-
244232
.segment-explorer-files {
245233
display: inline-flex;
246234
gap: 8px;

packages/next/src/server/app-render/create-component-tree.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,10 @@ function normalizeConventionFilePath(
10331033
conventionPath: string | undefined
10341034
) {
10351035
const cwd = process.env.NEXT_RUNTIME === 'edge' ? '' : process.cwd()
1036-
const relativePath = (conventionPath || '')
1036+
const nextInternalPrefixRegex =
1037+
/^(.*[\\/])?next[\\/]dist[\\/]client[\\/]components[\\/]/
1038+
1039+
let relativePath = (conventionPath || '')
10371040
// remove turbopack [project] prefix
10381041
.replace(/^\[project\][\\/]/, '')
10391042
// remove the project root from the path
@@ -1043,6 +1046,11 @@ function normalizeConventionFilePath(
10431046
// remove /(src/)?app/ dir prefix
10441047
.replace(/^([\\/])*(src[\\/])?app[\\/]/, '')
10451048

1049+
// If it's internal file only keep the filename, strip nextjs internal prefix
1050+
if (nextInternalPrefixRegex.test(relativePath)) {
1051+
relativePath = relativePath.replace(nextInternalPrefixRegex, '')
1052+
}
1053+
10461054
return relativePath
10471055
}
10481056

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import Link from 'next/link'
2+
3+
const hrefs = [
4+
'/parallel-routes',
5+
'/blog/~/grid',
6+
'/soft-navigation/a',
7+
'/file-segments',
8+
]
9+
10+
export default function Page() {
11+
return (
12+
<div>
13+
<h1>Segment Explorer</h1>
14+
<p>Examples</p>
15+
<div>
16+
{hrefs.map((href) => (
17+
<div key={href}>
18+
<Link href={href}>{href}</Link>
19+
</div>
20+
))}
21+
</div>
22+
</div>
23+
)
24+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use client'
2+
3+
export default function Page() {
4+
if (typeof window !== 'undefined') {
5+
throw new Error('Error on client')
6+
}
7+
return <p>page</p>
8+
}

test/development/app-dir/segment-explorer/segment-explorer.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,13 @@ describe('segment-explorer', () => {
114114
`"Route Info currently is only available for the App Router."`
115115
)
116116
})
117+
118+
it('should handle special built-in not-found segments', async () => {
119+
const browser = await next.browser('/404')
120+
expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
121+
"app/
122+
layout.tsx
123+
not-found-error.js"
124+
`)
125+
})
117126
})

0 commit comments

Comments
 (0)