react/compiler/packages/react-mcp-server/src/utils/runtimePerf.ts
lauren 12b094d2f6
[mcp] Update plugins (#33082)
Adds typescript support.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33082).
* #33085
* #33084
* #33083
* __->__ #33082
* #33101
2025-05-02 13:56:45 -04:00

148 lines
5.1 KiB
TypeScript

import * as babel from '@babel/core';
import puppeteer from 'puppeteer';
export async function measurePerformance(code: string) {
const babelOptions = {
configFile: false,
babelrc: false,
presets: [
'@babel/preset-typescript',
'@babel/preset-env',
'@babel/preset-react',
],
};
// Parse the code to AST
const parsed = await babel.parseAsync(code, babelOptions);
if (!parsed) {
throw new Error('Failed to parse code');
}
// Transform AST to browser-compatible JavaScript
const transformResult = await babel.transformFromAstAsync(parsed, undefined, {
...babelOptions,
filename: 'file.jsx',
plugins: [
() => ({
visitor: {
ImportDeclaration(
path: babel.NodePath<babel.types.ImportDeclaration>,
) {
const value = path.node.source.value;
if (value === 'react' || value === 'react-dom') {
path.remove();
}
},
},
}),
],
});
const transpiled = transformResult?.code || undefined;
if (!transpiled) {
throw new Error('Failed to transpile code');
}
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({width: 1280, height: 720});
const html = buildHtml(transpiled);
await page.setContent(html, {waitUntil: 'networkidle0'});
await page.waitForFunction(
'window.__RESULT__ !== undefined && (window.__RESULT__.renderTime !== null || window.__RESULT__.error !== null)',
);
const result = await page.evaluate(() => {
return (window as any).__RESULT__;
});
await browser.close();
return result;
}
function buildHtml(transpiled: string) {
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>React Performance Test</title>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/web-vitals@3.0.0/dist/web-vitals.iife.js"></script>
<style>
body { margin: 0; }
#root { padding: 20px; }
</style>
</head>
<body>
<div id="root"></div>
<script>
window.__RESULT__ = {
renderTime: null,
webVitals: {},
reactProfilerMetrics: {},
error: null
};
webVitals.onCLS((metric) => { window.__RESULT__.webVitals.cls = metric; });
webVitals.onLCP((metric) => { window.__RESULT__.webVitals.lcp = metric; });
webVitals.onINP((metric) => { window.__RESULT__.webVitals.inp = metric; });
webVitals.onFID((metric) => { window.__RESULT__.webVitals.fid = metric; });
webVitals.onTTFB((metric) => { window.__RESULT__.webVitals.ttfb = metric; });
try {
${transpiled}
window.App = App;
// Render the component to the DOM with profiling
const AppComponent = window.App || (() => React.createElement('div', null, 'No App component exported'));
const root = ReactDOM.createRoot(document.getElementById('root'), {
onUncaughtError: (error, errorInfo) => {
window.__RESULT__.error = error;
}
});
const renderStart = performance.now()
root.render(
React.createElement(React.Profiler, {
id: 'App',
onRender: (id, phase, actualDuration, baseDuration, startTime, commitTime) => {
window.__RESULT__.reactProfilerMetrics.id = id;
window.__RESULT__.reactProfilerMetrics.phase = phase;
window.__RESULT__.reactProfilerMetrics.actualDuration = actualDuration;
window.__RESULT__.reactProfilerMetrics.baseDuration = baseDuration;
window.__RESULT__.reactProfilerMetrics.startTime = startTime;
window.__RESULT__.reactProfilerMetrics.commitTime = commitTime;
}
}, React.createElement(AppComponent))
);
const renderEnd = performance.now();
window.__RESULT__.renderTime = renderEnd - renderStart;
} catch (error) {
console.error('Error rendering component:', error);
window.__RESULT__.error = {
message: error.message,
stack: error.stack
};
}
</script>
<script>
window.onerror = function(message, url, lineNumber) {
window.__RESULT__.error = message;
};
</script>
</body>
</html>
`;
return html;
}