Skip to content

Commit

Permalink
Enable react profiling option for app dir client components
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Jun 28, 2023
1 parent f2dc6c8 commit 5abf3fb
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 23 deletions.
34 changes: 24 additions & 10 deletions packages/next/src/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,17 @@ export function getDefineEnv({
}
}

function getReactProfilingInProduction() {
return {
'react-dom$': 'react-dom/profiling',
'scheduler/tracing': 'scheduler/tracing-profiling',
}
}

function createRSCAliases(
bundledReactChannel: string,
opts: {
reactProductionProfiling: boolean
reactSharedSubset: boolean
reactDomServerRenderingStub: boolean
reactServerCondition?: boolean
Expand Down Expand Up @@ -455,6 +463,15 @@ function createRSCAliases(
}
}

if (opts.reactProductionProfiling) {
alias[
'react-dom$'
] = `next/dist/compiled/react-dom${bundledReactChannel}/profiling`
alias[
'scheduler/tracing'
] = `next/dist/compiled/scheduler${bundledReactChannel}/tracing-profiling`
}

return alias
}

Expand Down Expand Up @@ -998,15 +1015,6 @@ export default async function getBaseWebpackConfig(
} as ClientEntries)
: undefined

function getReactProfilingInProduction() {
if (reactProductionProfiling) {
return {
'react-dom$': 'react-dom/profiling',
'scheduler/tracing': 'scheduler/tracing-profiling',
}
}
}

// tell webpack where to look for _app and _document
// using aliases to allow falling back to the default
// version when removed or not present
Expand Down Expand Up @@ -1145,7 +1153,7 @@ export default async function getBaseWebpackConfig(
[ROOT_DIR_ALIAS]: dir,
[DOT_NEXT_ALIAS]: distDir,
...(isClient || isEdgeServer ? getOptimizedAliases() : {}),
...getReactProfilingInProduction(),
...(reactProductionProfiling ? getReactProfilingInProduction() : {}),

[RSC_ACTION_VALIDATE_ALIAS]:
'next/dist/build/webpack/loaders/next-flight-loader/action-validate',
Expand Down Expand Up @@ -1933,6 +1941,7 @@ export default async function getBaseWebpackConfig(
...createRSCAliases(bundledReactChannel, {
reactSharedSubset: false,
reactDomServerRenderingStub: false,
reactProductionProfiling,
}),
},
},
Expand Down Expand Up @@ -1965,6 +1974,8 @@ export default async function getBaseWebpackConfig(
reactSharedSubset: true,
reactDomServerRenderingStub: true,
reactServerCondition: true,
// No server components profiling
reactProductionProfiling,
}),
},
},
Expand Down Expand Up @@ -2028,6 +2039,7 @@ export default async function getBaseWebpackConfig(
reactSharedSubset: true,
reactDomServerRenderingStub: true,
reactServerCondition: true,
reactProductionProfiling,
}),
},
},
Expand All @@ -2041,6 +2053,7 @@ export default async function getBaseWebpackConfig(
reactSharedSubset: false,
reactDomServerRenderingStub: true,
reactServerCondition: false,
reactProductionProfiling,
}),
},
},
Expand All @@ -2057,6 +2070,7 @@ export default async function getBaseWebpackConfig(
reactSharedSubset: false,
reactDomServerRenderingStub: false,
reactServerCondition: false,
reactProductionProfiling,
}),
},
},
Expand Down
3 changes: 3 additions & 0 deletions packages/next/src/server/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,9 @@ const configSchema = {
publicRuntimeConfig: {
type: 'object',
},
reactProductionProfiling: {
type: 'boolean',
},
reactStrictMode: {
type: 'boolean',
},
Expand Down
7 changes: 7 additions & 0 deletions packages/next/src/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,12 @@ export interface NextConfig extends Record<string, any> {
*/
optimizeFonts?: boolean

/**
* Enable react profiling in production
*
*/
reactProductionProfiling?: boolean

/**
* The Next.js runtime is Strict Mode-compliant.
*
Expand Down Expand Up @@ -670,6 +676,7 @@ export const defaultConfig: NextConfig = {
excludeDefaultMomentLocales: true,
serverRuntimeConfig: {},
publicRuntimeConfig: {},
reactProductionProfiling: false,
reactStrictMode: false,
httpAgentOptions: {
keepAlive: true,
Expand Down
1 change: 0 additions & 1 deletion packages/next/taskfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1760,7 +1760,6 @@ export async function copy_vendor_react(task_) {
'static.browser.js',
'unstable_testing.js',
'test-utils.js',
'profiling.js',
'server.bun.js',
'cjs/react-dom-server.bun.development.js',
'cjs/react-dom-server.bun.production.min.js',
Expand Down
2 changes: 1 addition & 1 deletion test/integration/react-profiling-mode/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const Index = () => {
window.profileResults.push(res)
}}
>
<p>hello world</p>
<p>hello pages</p>
</React.Profiler>
)
}
Expand Down
41 changes: 30 additions & 11 deletions test/integration/react-profiling-mode/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,22 @@ let app
describe('React Profiling Mode', () => {
describe('without config enabled', () => {
beforeAll(async () => {
await fs.remove(nextConfig)
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
afterAll(async () => {
await fs.writeFile(
nextConfig,
`
module.exports = {
reactProductionProfiling: true
}
`
)
await killApp(app)
})

it('should not have used the react-dom profiling bundle', async () => {
const browser = await webdriver(appPort, '/')
Expand All @@ -30,29 +41,37 @@ describe('React Profiling Mode', () => {

describe('with config enabled', () => {
beforeAll(async () => {
await fs.writeFile(
nextConfig,
`
module.exports = {
reactProductionProfiling: true
}
`
)
await nextBuild(appDir, ['--profile'])
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await fs.remove(nextConfig)
await killApp(app)
})

it('should have used the react-dom profiling bundle', async () => {
it('should have used the react-dom profiling bundle for pages', async () => {
const browser = await webdriver(appPort, '/')
const results = await browser.eval('window.profileResults')

expect(results.length).toBe(1)
expect(results[0] && results[0][0]).toBe('hello')
})

it('should have used the react-dom profiling bundle for client component', async () => {
const browser = await webdriver(appPort, '/client')
const results = await browser.eval('window.profileResults')

expect(results.length).toBe(1)
expect(results[0] && results[0][0]).toBe('hello-app-client')
})

it('should have used the react-dom profiling bundle for server component', async () => {
// Can't test react Profiler API in server components but make sure rendering works
const browser = await webdriver(appPort, '/server')

expect(await browser.waitForElementByCss('p').text()).toBe(
'hello app server'
)
})
})
})

0 comments on commit 5abf3fb

Please sign in to comment.