Files
react/fixtures/flight/loader/region.js
T
Sebastian Markbåge ba099e442b [Flight] Add findSourceMapURL option to get a URL to load Server source maps from (#29708)
This lets you click a stack frame on the client and see the Server
source code inline.

<img width="871" alt="Screenshot 2024-06-01 at 11 44 24 PM"
src="https://github.com/facebook/react/assets/63648/581281ce-0dce-40c0-a084-4a6d53ba1682">

<img width="840" alt="Screenshot 2024-06-01 at 11 43 37 PM"
src="https://github.com/facebook/react/assets/63648/00dc77af-07c1-4389-9ae0-cf1f45199efb">

We could do some logic on the server that sends a source map url for
every stack frame in the RSC payload. That would make the client
potentially config free. However regardless we need the config to
describe what url scheme to use since that’s not built in to the bundler
config. In practice you likely have a common pattern for your source
maps so no need to send data over and over when we can just have a
simple function configured on the client.

The server must return a source map, even if the file is not actually
compiled since the fake file is still compiled.

The source mapping strategy can be one of two models depending on if the
server’s stack traces (`new Error().stack`) are source mapped back to
the original (`—enable-source-maps`) or represents the location in
compiled code (like in the browser).

If it represents the location in compiled code it’s actually easier. You
just serve the source map generated for that file by the tooling.

If it is already source mapped it has to generate a source map where
everything points to the same location (as if not compiled) ideally with
a segment per logical ast node.
2024-06-02 22:58:24 -04:00

75 lines
2.2 KiB
JavaScript

import {
resolve,
load as reactLoad,
getSource as getSourceImpl,
transformSource as reactTransformSource,
} from 'react-server-dom-webpack/node-loader';
export {resolve};
import babel from '@babel/core';
const babelOptions = {
babelrc: false,
ignore: [/\/(build|node_modules)\//],
plugins: [
'@babel/plugin-syntax-import-meta',
'@babel/plugin-transform-react-jsx',
],
sourceMaps: process.env.NODE_ENV === 'development' ? 'inline' : false,
};
async function babelLoad(url, context, defaultLoad) {
const {format} = context;
const result = await defaultLoad(url, context, defaultLoad);
if (result.format === 'module') {
const opt = Object.assign({filename: url}, babelOptions);
const newResult = await babel.transformAsync(result.source, opt);
if (!newResult) {
if (typeof result.source === 'string') {
return result;
}
return {
source: Buffer.from(result.source).toString('utf8'),
format: 'module',
};
}
return {source: newResult.code, format: 'module'};
}
return defaultLoad(url, context, defaultLoad);
}
export async function load(url, context, defaultLoad) {
return await reactLoad(url, context, (u, c) => {
return babelLoad(u, c, defaultLoad);
});
}
async function babelTransformSource(source, context, defaultTransformSource) {
const {format} = context;
if (format === 'module') {
const opt = Object.assign({filename: context.url}, babelOptions);
const newResult = await babel.transformAsync(source, opt);
if (!newResult) {
if (typeof source === 'string') {
return {source};
}
return {
source: Buffer.from(source).toString('utf8'),
};
}
return {source: newResult.code};
}
return defaultTransformSource(source, context, defaultTransformSource);
}
async function transformSourceImpl(source, context, defaultTransformSource) {
return await reactTransformSource(source, context, (s, c) => {
return babelTransformSource(s, c, defaultTransformSource);
});
}
export const transformSource =
process.version < 'v16' ? transformSourceImpl : undefined;
export const getSource = process.version < 'v16' ? getSourceImpl : undefined;