Skip to content

Commit 007b4b4

Browse files
committed
[mcp] Refactor
Summary: Test Plan: Reviewers: Subscribers: Tasks: Tags:
1 parent 236538c commit 007b4b4

File tree

2 files changed

+106
-78
lines changed

2 files changed

+106
-78
lines changed

compiler/packages/react-mcp-server/src/index.ts

Lines changed: 10 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -387,72 +387,26 @@ server.tool(
387387
`,
388388
{
389389
text: z.string(),
390+
iterations: z.number().optional().default(2),
390391
},
391-
async ({text}) => {
392+
async ({text, iterations}) => {
392393
try {
393-
const iterations = 20;
394-
395-
let perfData = {
396-
renderTime: 0,
397-
webVitals: {
398-
cls: 0,
399-
lcp: 0,
400-
inp: 0,
401-
fid: 0,
402-
ttfb: 0,
403-
},
404-
reactProfilerMetrics: {
405-
id: 0,
406-
phase: 0,
407-
actualDuration: 0,
408-
baseDuration: 0,
409-
startTime: 0,
410-
commitTime: 0,
411-
},
412-
error: null,
413-
};
414-
415-
for (let i = 0; i < iterations; i++) {
416-
const performanceResults = await measurePerformance(text);
417-
perfData.renderTime += performanceResults.renderTime;
418-
perfData.webVitals.cls += performanceResults.webVitals.cls || 0;
419-
perfData.webVitals.lcp += performanceResults.webVitals.lcp || 0;
420-
perfData.webVitals.inp += performanceResults.webVitals.inp || 0;
421-
perfData.webVitals.fid += performanceResults.webVitals.fid || 0;
422-
perfData.webVitals.ttfb += performanceResults.webVitals.ttfb || 0;
423-
424-
perfData.reactProfilerMetrics.id +=
425-
performanceResults.reactProfilerMetrics.actualDuration || 0;
426-
perfData.reactProfilerMetrics.phase +=
427-
performanceResults.reactProfilerMetrics.phase || 0;
428-
perfData.reactProfilerMetrics.actualDuration +=
429-
performanceResults.reactProfilerMetrics.actualDuration || 0;
430-
perfData.reactProfilerMetrics.baseDuration +=
431-
performanceResults.reactProfilerMetrics.baseDuration || 0;
432-
perfData.reactProfilerMetrics.startTime +=
433-
performanceResults.reactProfilerMetrics.startTime || 0;
434-
perfData.reactProfilerMetrics.commitTime +=
435-
performanceResults.reactProfilerMetrics.commitTime || 0;
436-
}
437-
394+
const results = await measurePerformance(text, iterations);
438395
const formattedResults = `
439396
# React Component Performance Results
440397
441398
## Mean Render Time
442-
${perfData.renderTime / iterations}ms
399+
${results.renderTime / iterations}ms
443400
444401
## Mean Web Vitals
445-
- Cumulative Layout Shift (CLS): ${perfData.webVitals.cls / iterations}
446-
- Largest Contentful Paint (LCP): ${perfData.webVitals.lcp / iterations}ms
447-
- Interaction to Next Paint (INP): ${perfData.webVitals.inp / iterations}ms
448-
- First Input Delay (FID): ${perfData.webVitals.fid / iterations}ms
449-
- Time to First Byte (TTFB): ${perfData.webVitals.ttfb / iterations}ms
402+
- Cumulative Layout Shift (CLS): ${results.webVitals.cls / iterations}ms
403+
- Largest Contentful Paint (LCP): ${results.webVitals.lcp / iterations}ms
404+
- Interaction to Next Paint (INP): ${results.webVitals.inp / iterations}ms
405+
- First Input Delay (FID): ${results.webVitals.fid / iterations}ms
450406
451407
## Mean React Profiler
452-
- Actual Duration: ${perfData.reactProfilerMetrics.actualDuration / iterations}ms
453-
- Base Duration: ${perfData.reactProfilerMetrics.baseDuration / iterations}ms
454-
- Start Time: ${perfData.reactProfilerMetrics.startTime / iterations}ms
455-
- Commit Time: ${perfData.reactProfilerMetrics.commitTime / iterations}ms
408+
- Actual Duration: ${results.reactProfiler.actualDuration / iterations}ms
409+
- Base Duration: ${results.reactProfiler.baseDuration / iterations}ms
456410
`;
457411

458412
return {

compiler/packages/react-mcp-server/src/tools/runtimePerf.ts

Lines changed: 96 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,30 @@
11
import * as babel from '@babel/core';
22
import puppeteer from 'puppeteer';
33

4-
export async function measurePerformance(code: string) {
4+
type PerformanceResults = {
5+
renderTime: number;
6+
webVitals: {
7+
cls: number;
8+
lcp: number;
9+
inp: number;
10+
fid: number;
11+
ttfb: number;
12+
};
13+
reactProfiler: {
14+
id: number;
15+
phase: number;
16+
actualDuration: number;
17+
baseDuration: number;
18+
startTime: number;
19+
commitTime: number;
20+
};
21+
error: Error | null;
22+
};
23+
24+
export async function measurePerformance(
25+
code: string,
26+
iterations: number,
27+
): Promise<PerformanceResults> {
528
const babelOptions = {
629
configFile: false,
730
babelrc: false,
@@ -42,23 +65,77 @@ export async function measurePerformance(code: string) {
4265
throw new Error('Failed to transpile code');
4366
}
4467

45-
const browser = await puppeteer.launch();
46-
68+
const browser = await puppeteer.launch({headless: false});
4769
const page = await browser.newPage();
4870
await page.setViewport({width: 1280, height: 720});
4971
const html = buildHtml(transpiled);
50-
await page.setContent(html, {waitUntil: 'networkidle0'});
5172

52-
await page.waitForFunction(
53-
'window.__RESULT__ !== undefined && (window.__RESULT__.renderTime !== null || window.__RESULT__.error !== null)',
54-
);
73+
let performanceResults: PerformanceResults = {
74+
renderTime: 0,
75+
webVitals: {
76+
cls: 0,
77+
lcp: 0,
78+
inp: 0,
79+
fid: 0,
80+
ttfb: 0,
81+
},
82+
reactProfiler: {
83+
id: 0,
84+
phase: 0,
85+
actualDuration: 0,
86+
baseDuration: 0,
87+
startTime: 0,
88+
commitTime: 0,
89+
},
90+
error: null,
91+
};
5592

56-
const result = await page.evaluate(() => {
57-
return (window as any).__RESULT__;
58-
});
93+
for (let ii = 0; ii < iterations; ii++) {
94+
await page.setContent(html, {waitUntil: 'networkidle0'});
95+
await page.waitForFunction(
96+
'window.__RESULT__ !== undefined && (window.__RESULT__.renderTime !== null || window.__RESULT__.error !== null)',
97+
);
98+
// ui chaos monkey
99+
await page.waitForFunction(`window.__RESULT__ !== undefined && (function() {
100+
for (const el of [...document.querySelectorAll('a'), ...document.querySelectorAll('button')]) {
101+
console.log(el);
102+
el.click();
103+
}
104+
return true;
105+
})() `);
106+
const evaluationResult: PerformanceResults = await page.evaluate(() => {
107+
return (window as any).__RESULT__;
108+
});
109+
110+
console.error(JSON.stringify(evaluationResult, null, 2));
111+
112+
// TODO: investigate why webvital metrics are not populating correctly
113+
performanceResults.renderTime += evaluationResult.renderTime;
114+
performanceResults.webVitals.cls += evaluationResult.webVitals.cls || 0;
115+
performanceResults.webVitals.lcp += evaluationResult.webVitals.lcp || 0;
116+
performanceResults.webVitals.inp += evaluationResult.webVitals.inp || 0;
117+
performanceResults.webVitals.fid += evaluationResult.webVitals.fid || 0;
118+
performanceResults.webVitals.ttfb += evaluationResult.webVitals.ttfb || 0;
119+
120+
performanceResults.reactProfiler.id +=
121+
evaluationResult.reactProfiler.actualDuration || 0;
122+
performanceResults.reactProfiler.phase +=
123+
evaluationResult.reactProfiler.phase || 0;
124+
performanceResults.reactProfiler.actualDuration +=
125+
evaluationResult.reactProfiler.actualDuration || 0;
126+
performanceResults.reactProfiler.baseDuration +=
127+
evaluationResult.reactProfiler.baseDuration || 0;
128+
performanceResults.reactProfiler.startTime +=
129+
evaluationResult.reactProfiler.startTime || 0;
130+
performanceResults.reactProfiler.commitTime +=
131+
evaluationResult.reactProfiler.commitTime || 0;
132+
133+
performanceResults.error = evaluationResult.error;
134+
}
59135

60136
await browser.close();
61-
return result;
137+
138+
return performanceResults;
62139
}
63140

64141
function buildHtml(transpiled: string) {
@@ -82,7 +159,7 @@ function buildHtml(transpiled: string) {
82159
window.__RESULT__ = {
83160
renderTime: null,
84161
webVitals: {},
85-
reactProfilerMetrics: {},
162+
reactProfiler: {},
86163
error: null
87164
};
88165
@@ -112,12 +189,12 @@ function buildHtml(transpiled: string) {
112189
React.createElement(React.Profiler, {
113190
id: 'App',
114191
onRender: (id, phase, actualDuration, baseDuration, startTime, commitTime) => {
115-
window.__RESULT__.reactProfilerMetrics.id = id;
116-
window.__RESULT__.reactProfilerMetrics.phase = phase;
117-
window.__RESULT__.reactProfilerMetrics.actualDuration = actualDuration;
118-
window.__RESULT__.reactProfilerMetrics.baseDuration = baseDuration;
119-
window.__RESULT__.reactProfilerMetrics.startTime = startTime;
120-
window.__RESULT__.reactProfilerMetrics.commitTime = commitTime;
192+
window.__RESULT__.reactProfiler.id = id;
193+
window.__RESULT__.reactProfiler.phase = phase;
194+
window.__RESULT__.reactProfiler.actualDuration = actualDuration;
195+
window.__RESULT__.reactProfiler.baseDuration = baseDuration;
196+
window.__RESULT__.reactProfiler.startTime = startTime;
197+
window.__RESULT__.reactProfiler.commitTime = commitTime;
121198
}
122199
}, React.createElement(AppComponent))
123200
);
@@ -127,10 +204,7 @@ function buildHtml(transpiled: string) {
127204
window.__RESULT__.renderTime = renderEnd - renderStart;
128205
} catch (error) {
129206
console.error('Error rendering component:', error);
130-
window.__RESULT__.error = {
131-
message: error.message,
132-
stack: error.stack
133-
};
207+
window.__RESULT__.error = error;
134208
}
135209
</script>
136210
<script>

0 commit comments

Comments
 (0)