Skip to content
Merged
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
5 changes: 2 additions & 3 deletions crates/next-core/src/next_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -801,9 +801,8 @@ pub struct ExperimentalConfig {
global_not_found: Option<bool>,
/// Defaults to false in development mode, true in production mode.
turbopack_remove_unused_exports: Option<bool>,
/// Devtool option for new panel UI.
#[serde(rename = "devtoolNewPanelUI")]
devtool_new_panel_ui: Option<bool>,
/// Devtool option for the segment explorer.
devtool_segment_explorer: Option<bool>,
}

#[derive(
Expand Down
3 changes: 3 additions & 0 deletions packages/next/src/build/define-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ export function getDefineEnv({
),
}
: {}),
'process.env.__NEXT_DEVTOOL_SEGMENT_EXPLORER':
// Enable segment explorer in devtools
isDevToolPanelUIEnabled || !!config.experimental.devtoolSegmentExplorer,
'process.env.__NEXT_DEVTOOL_NEW_PANEL_UI': isDevToolPanelUIEnabled,

// The devtools need to know whether or not to show an option to clear the
Expand Down
3 changes: 2 additions & 1 deletion packages/next/src/build/templates/app-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,8 @@ export async function handler(
deploymentId: nextConfig.deploymentId,
enableTainting: nextConfig.experimental.taint,
htmlLimitedBots: nextConfig.htmlLimitedBots,
devtoolNewPanelUI: nextConfig.experimental.devtoolNewPanelUI,
devtoolSegmentExplorer:
nextConfig.experimental.devtoolSegmentExplorer,
reactMaxHeadersLength: nextConfig.reactMaxHeadersLength,

multiZoneDraftMode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export function getRender({
serverActionsManifest,
serverActions,
nextFontManifest,
devtoolNewPanelUI: config.experimental.devtoolNewPanelUI,
devtoolSegmentExplorer: config.experimental.devtoolSegmentExplorer,
},
renderToHTML,
incrementalCacheHandler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function DevToolsIndicator({
[vertical]: `${INDICATOR_PADDING}px`,
[horizontal]: `${INDICATOR_PADDING}px`,
visibility:
state.isDevToolsPanelOpen && !state.isErrorOverlayOpen
state.isDevToolsPanelOpen || state.isErrorOverlayOpen
? 'hidden'
: 'visible',
} as CSSProperties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,7 @@ export function DevToolsPanel({
>
<div data-nextjs-devtools-panel-header-tab-group>
<button
data-nextjs-devtools-panel-header-tab="issues"
data-nextjs-devtools-panel-header-tab-active={
data-nextjs-devtools-panel-header-tab={
activeTab === 'issues'
}
onClick={() => setActiveTab('issues')}
Expand All @@ -177,17 +176,15 @@ export function DevToolsPanel({
) : null}
</button>
<button
data-nextjs-devtools-panel-header-tab="route"
data-nextjs-devtools-panel-header-tab-active={
data-nextjs-devtools-panel-header-tab={
activeTab === 'route'
}
onClick={() => setActiveTab('route')}
>
Route Info
</button>
<button
data-nextjs-devtools-panel-header-tab="settings"
data-nextjs-devtools-panel-header-tab-active={
data-nextjs-devtools-panel-header-tab={
activeTab === 'settings'
}
onClick={() => setActiveTab('settings')}
Expand Down Expand Up @@ -355,7 +352,7 @@ export const DEVTOOLS_PANEL_STYLES = css`
}
}

[data-nextjs-devtools-panel-header-tab-active='true'] {
[data-nextjs-devtools-panel-header-tab='true'] {
color: var(--color-gray-1000);
background-color: var(--color-gray-100);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
type DevToolsScale,
} from './dev-tools-info/preferences'
import { Draggable } from './draggable'
import { SegmentsExplorer } from './dev-tools-info/segments-explorer'

// TODO: add E2E tests to cover different scenarios

Expand Down Expand Up @@ -83,6 +84,7 @@ const OVERLAYS = {
Turbo: 'turbo',
Route: 'route',
Preferences: 'preferences',
SegmentExplorer: 'segment-explorer',
} as const

export type Overlays = (typeof OVERLAYS)[keyof typeof OVERLAYS]
Expand Down Expand Up @@ -128,6 +130,7 @@ function DevToolsPopover({
const isTurbopackInfoOpen = open === OVERLAYS.Turbo
const isRouteInfoOpen = open === OVERLAYS.Route
const isPreferencesOpen = open === OVERLAYS.Preferences
const isSegmentExplorerOpen = open === OVERLAYS.SegmentExplorer

const { mounted: menuMounted, rendered: menuRendered } = useDelayedRender(
isMenuOpen,
Expand Down Expand Up @@ -217,9 +220,7 @@ function DevToolsPopover({
}

function toggleErrorOverlay() {
if (!process.env.__NEXT_DEVTOOL_NEW_PANEL_UI) {
dispatch({ type: ACTION_ERROR_OVERLAY_TOGGLE })
}
dispatch({ type: ACTION_ERROR_OVERLAY_TOGGLE })
}

function closeToRootMenu() {
Expand Down Expand Up @@ -335,6 +336,19 @@ function DevToolsPopover({
setScale={setScale}
/>

{/* Page Route Info */}
{process.env.__NEXT_DEVTOOL_SEGMENT_EXPLORER ? (
<SegmentsExplorer
isOpen={isSegmentExplorerOpen}
close={closeToRootMenu}
triggerRef={triggerRef}
style={popover}
routerType={routerType}
// dummy page for legacy segment explorer, will be removed in the future
page={''}
/>
) : null}

{/* Dropdown Menu */}
{menuMounted && (
<div
Expand Down Expand Up @@ -400,6 +414,15 @@ function DevToolsPopover({
onClick={() => setOpen(OVERLAYS.Preferences)}
index={isTurbopack ? 2 : 3}
/>
{process.env.__NEXT_DEVTOOL_SEGMENT_EXPLORER ? (
<MenuItem
data-segment-explorer
label="Route Info"
value={<ChevronRight />}
onClick={() => setOpen(OVERLAYS.SegmentExplorer)}
index={isTurbopack ? 3 : 4}
/>
) : null}
</div>
</Context.Provider>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PageSegmentTree } from '../../../overview/segment-explorer'
import { DevToolsInfo, type DevToolsInfoPropsCore } from './dev-tools-info'

export function SegmentsExplorer({
routerType,
page,
...props
}: DevToolsInfoPropsCore &
React.HTMLProps<HTMLDivElement> & {
routerType: 'app' | 'pages'
page: string
}) {
const isAppRouter = routerType === 'app'
return (
<DevToolsInfo title="Route Info" {...props}>
<div data-nextjs-segments-explorer>
<PageSegmentTree isAppRouter={isAppRouter} page={page} />
</div>
</DevToolsInfo>
)
}

export const SEGMENTS_EXPLORER_STYLES = `
[data-nextjs-segments-explorer] {
margin: -12px -8px;
}
`
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { DEVTOOLS_PANEL_TAB_ISSUES_CONTENT_STYLES } from '../components/devtools
import { ISSUE_FEEDBACK_BUTTON_STYLES } from '../components/errors/error-overlay-toolbar/issue-feedback-button'
import { ERROR_CONTENT_SKELETON_STYLES } from '../container/runtime-error/error-content-skeleton'
import { SEGMENTS_EXPLORER_TAB_STYLES } from '../components/devtools-panel/devtools-panel-tab/segments-explorer-tab'
import { SEGMENTS_EXPLORER_STYLES } from '../components/errors/dev-tools-indicator/dev-tools-info/segments-explorer'
import { DEVTOOLS_PANEL_TAB_ISSUES_CONTENT_LAYOUT_STYLES } from '../components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-content-layout'
import { DEVTOOLS_PANEL_TAB_ISSUES_EMPTY_CONTENT_STYLES } from '../components/devtools-panel/devtools-panel-tab/issues-tab/issues-tab-empty-content'

Expand Down Expand Up @@ -67,6 +68,7 @@ export function ComponentStyles() {
${DEV_TOOLS_INFO_TURBOPACK_INFO_STYLES}
${DEV_TOOLS_INFO_ROUTE_INFO_STYLES}
${DEV_TOOLS_INFO_USER_PREFERENCES_STYLES}
${SEGMENTS_EXPLORER_STYLES}
${DEV_TOOLS_INFO_RENDER_FILES_STYLES}
${FADER_STYLES}
${DEVTOOLS_PANEL_STYLES}
Expand Down
2 changes: 1 addition & 1 deletion packages/next/src/server/app-render/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3977,7 +3977,7 @@ const getGlobalErrorStyles = async (
dir,
globalErrorModule?.[1]
)
if (ctx.renderOpts.devtoolNewPanelUI && globalErrorModulePath) {
if (ctx.renderOpts.devtoolSegmentExplorer && globalErrorModulePath) {
const SegmentViewNode = ctx.componentMod.SegmentViewNode
globalErrorStyles = (
// This will be rendered next to GlobalError component under ErrorBoundary,
Expand Down
6 changes: 4 additions & 2 deletions packages/next/src/server/app-render/create-component-tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,8 @@ async function createComponentTreeInternal({
// Resolve the segment param
const actualSegment = segmentParam ? segmentParam.treeSegment : segment
const isSegmentViewEnabled =
process.env.NODE_ENV === 'development' && ctx.renderOpts.devtoolNewPanelUI
process.env.NODE_ENV === 'development' &&
ctx.renderOpts.devtoolSegmentExplorer
const dir =
process.env.NEXT_RUNTIME === 'edge'
? process.env.__NEXT_EDGE_PROJECT_DIR!
Expand Down Expand Up @@ -1083,7 +1084,8 @@ async function createBoundaryConventionElement({
tree: LoaderTree
}) {
const isSegmentViewEnabled =
process.env.NODE_ENV === 'development' && ctx.renderOpts.devtoolNewPanelUI
process.env.NODE_ENV === 'development' &&
ctx.renderOpts.devtoolSegmentExplorer
const dir =
process.env.NEXT_RUNTIME === 'edge'
? process.env.__NEXT_EDGE_PROJECT_DIR!
Expand Down
4 changes: 2 additions & 2 deletions packages/next/src/server/app-render/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,9 @@ export interface RenderOptsPartial {
allowEmptyStaticShell?: boolean

/**
* next config experimental.devtoolNewPanelUI
* next config experimental.devtoolSegmentExplorer
*/
devtoolNewPanelUI?: boolean
devtoolSegmentExplorer?: boolean
}

export type RenderOpts = LoadComponentsReturnType<AppPageModule> &
Expand Down
3 changes: 2 additions & 1 deletion packages/next/src/server/base-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,8 @@ export default abstract class Server<
onInstrumentationRequestError:
this.instrumentationOnRequestError.bind(this),
reactMaxHeadersLength: this.nextConfig.reactMaxHeadersLength,
devtoolNewPanelUI: this.nextConfig.experimental.devtoolNewPanelUI,
devtoolSegmentExplorer:
this.nextConfig.experimental.devtoolSegmentExplorer,
}

// Initialize next/config with the environment configuration
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/server/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ export const configSchema: zod.ZodType<NextConfig> = z.lazy(() =>
})
.optional(),
globalNotFound: z.boolean().optional(),
devtoolSegmentExplorer: z.boolean().optional(),
devtoolNewPanelUI: z.boolean().optional(),
})
.optional(),
Expand Down
6 changes: 6 additions & 0 deletions packages/next/src/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,11 @@ export interface ExperimentalConfig {
*/
globalNotFound?: boolean

/**
* Enable segment viewer for the app directory in Next.js DevTools.
*/
devtoolSegmentExplorer?: boolean

/**
* Enable new panel UI for the Next.js DevTools.
*/
Expand Down Expand Up @@ -1451,6 +1456,7 @@ export const defaultConfig = {
useCache: undefined,
slowModuleDetection: undefined,
globalNotFound: false,
devtoolSegmentExplorer: false,
},
htmlLimitedBots: undefined,
bundlePagesRouterDependencies: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
const nextConfig = {
experimental: {
devtoolNewPanelUI: true,
devtoolSegmentExplorer: true,
authInterrupts: true,
globalNotFound: true,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { openDevToolsIndicatorPopover } from 'next-test-utils'
import { Playwright } from 'next-webdriver'

async function getSegmentExplorerContent(browser: Playwright) {
// open the devtool button
await openDevToolsIndicatorPopover(browser)

// open segment explorer tab
await browser
.elementByCss('[data-nextjs-devtools-panel-header-tab="route"]')
.click()
// open the segment explorer
await browser.elementByCss('[data-segment-explorer]').click()

// wait for the segment explorer to be visible
await browser.waitForElementByCss('[data-nextjs-devtool-segment-explorer]')
Expand Down
2 changes: 1 addition & 1 deletion test/development/app-dir/segment-explorer/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
const nextConfig = {
experimental: {
devtoolNewPanelUI: true,
devtoolSegmentExplorer: true,
authInterrupts: true,
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ async function getSegmentExplorerContent(browser: Playwright) {
// open the devtool button
await openDevToolsIndicatorPopover(browser)

// open segment explorer tab
await browser
.elementByCss('[data-nextjs-devtools-panel-header-tab="route"]')
.click()
// open the segment explorer
await browser.elementByCss('[data-segment-explorer]').click()

// wait for the segment explorer to be visible
await browser.waitForElementByCss('[data-nextjs-devtool-segment-explorer]')
Expand Down Expand Up @@ -88,7 +86,6 @@ describe('segment-explorer', () => {
await browser.elementByCss('[href="/soft-navigation/b"]').click()
await retry(async () => {
expect(await browser.elementByCss('body').text()).toContain('Page B')
expect(await browser.url()).toBe(`${next.url}/soft-navigation/b`)
})

expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
Expand Down
5 changes: 0 additions & 5 deletions test/lib/next-test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -951,11 +951,6 @@ export async function openRedbox(browser: Playwright): Promise<void> {
export async function openDevToolsIndicatorPopover(
browser: Playwright
): Promise<void> {
// If the devtools panel is already open, we don't assert the indicator,
// and no need to open it again.
if (await hasDevToolsPanel(browser)) {
return
}
const devToolsIndicator = await assertHasDevToolsIndicator(browser)

try {
Expand Down
Loading