rsbuild-plugin-react-router
Version:
React Router plugin for Rsbuild
726 lines (709 loc) • 41.3 kB
JavaScript
import { fileURLToPath as __webpack_fileURLToPath__ } from "node:url";
import { dirname as __webpack_dirname__ } from "node:path";
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
import * as __WEBPACK_EXTERNAL_MODULE_fs_extra_ce68a66b__ from "fs-extra";
import * as __WEBPACK_EXTERNAL_MODULE_esbuild__ from "esbuild";
import * as __WEBPACK_EXTERNAL_MODULE_jiti__ from "jiti";
import * as __WEBPACK_EXTERNAL_MODULE_jsesc__ from "jsesc";
import * as __WEBPACK_EXTERNAL_MODULE_pathe__ from "pathe";
import * as __WEBPACK_EXTERNAL_MODULE_rspack_plugin_virtual_module_609978fd__ from "rspack-plugin-virtual-module";
import * as __WEBPACK_EXTERNAL_MODULE__babel_parser_31177a12__ from "@babel/parser";
import * as __WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__ from "@babel/types";
import * as __WEBPACK_EXTERNAL_MODULE__react_router_node_fff52f02__ from "@react-router/node";
import * as __WEBPACK_EXTERNAL_MODULE_babel_dead_code_elimination_8901ce62__ from "babel-dead-code-elimination";
var __webpack_modules__ = {
"@babel/generator": function(module) {
module.exports = require("@babel/generator");
},
"@babel/traverse": function(module) {
module.exports = require("@babel/traverse");
}
}, __webpack_module_cache__ = {};
function __webpack_require__(moduleId) {
var cachedModule = __webpack_module_cache__[moduleId];
if (void 0 !== cachedModule) return cachedModule.exports;
var module = __webpack_module_cache__[moduleId] = {
exports: {}
};
return __webpack_modules__[moduleId](module, module.exports, __webpack_require__), module.exports;
}
let traverse = __webpack_require__("@babel/traverse").default, generate = __webpack_require__("@babel/generator").default, JS_EXTENSIONS = [
'.tsx',
'.ts',
'.jsx',
'.js',
'.mjs'
], JS_LOADERS = {
'.ts': 'ts',
'.tsx': 'tsx',
'.js': 'js',
'.jsx': 'jsx'
}, SERVER_ONLY_ROUTE_EXPORTS = [
'loader',
'action',
'headers'
], NAMED_COMPONENT_EXPORTS = [
'HydrateFallback',
'ErrorBoundary'
], SERVER_EXPORTS = {
loader: 'loader',
action: 'action'
}, CLIENT_EXPORTS = {
clientAction: 'clientAction',
clientLoader: 'clientLoader',
ErrorBoundary: 'ErrorBoundary'
}, createDevServerMiddleware = (server)=>async (req, res, next)=>{
try {
let bundle = await server.environments.node.loadBundle('app');
if (!bundle || !bundle.routes) throw Error('Server bundle not found or invalid');
let listener = (0, __WEBPACK_EXTERNAL_MODULE__react_router_node_fff52f02__.createRequestListener)({
build: bundle
});
await listener(req, res);
} catch (error) {
console.error('SSR Error:', error), next(error);
}
};
function invalidDestructureError(name) {
return Error(`Cannot remove destructured export "${name}"`);
}
function toFunctionExpression(decl) {
return __WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.functionExpression(decl.id, decl.params, decl.body, decl.generator, decl.async);
}
function combineURLs(baseURL, relativeURL) {
return relativeURL ? `${baseURL.replace(/\/+$/, '')}/${relativeURL.replace(/^\/+/, '')}` : baseURL;
}
function findEntryFile(basePath) {
for (let ext of JS_EXTENSIONS){
let filePath = `${basePath}${ext}`;
if ((0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(filePath)) return filePath;
}
return `${basePath}.tsx`;
}
let removeExports = (ast, exportsToRemove)=>{
let previouslyReferencedIdentifiers = (0, __WEBPACK_EXTERNAL_MODULE_babel_dead_code_elimination_8901ce62__.findReferencedIdentifiers)(ast), exportsFiltered = !1, markedForRemoval = new Set();
if (traverse(ast, {
ExportDeclaration (path) {
if ('ExportNamedDeclaration' === path.node.type) {
var _path_node_declaration, _path_node_declaration1, _path_node_declaration2;
if (path.node.specifiers.length && (path.node.specifiers = path.node.specifiers.filter((specifier)=>!('ExportSpecifier' === specifier.type && 'Identifier' === specifier.exported.type && exportsToRemove.includes(specifier.exported.name)) || (exportsFiltered = !0, !1)), 0 === path.node.specifiers.length && markedForRemoval.add(path)), (null === (_path_node_declaration = path.node.declaration) || void 0 === _path_node_declaration ? void 0 : _path_node_declaration.type) === 'VariableDeclaration') {
let declaration = path.node.declaration;
declaration.declarations = declaration.declarations.filter((declaration)=>'Identifier' === declaration.id.type && exportsToRemove.includes(declaration.id.name) ? (exportsFiltered = !0, !1) : (('ArrayPattern' === declaration.id.type || 'ObjectPattern' === declaration.id.type) && function validateDestructuredExports(id, exportsToRemove) {
if ('ArrayPattern' === id.type) {
for (let element of id.elements)if (element) {
if ('Identifier' === element.type && exportsToRemove.includes(element.name)) throw invalidDestructureError(element.name);
if ('RestElement' === element.type && 'Identifier' === element.argument.type && exportsToRemove.includes(element.argument.name)) throw invalidDestructureError(element.argument.name);
('ArrayPattern' === element.type || 'ObjectPattern' === element.type) && validateDestructuredExports(element, exportsToRemove);
}
}
if ('ObjectPattern' === id.type) {
for (let property of id.properties)if (property) {
if ('ObjectProperty' === property.type && 'Identifier' === property.key.type) {
if ('Identifier' === property.value.type && exportsToRemove.includes(property.value.name)) throw invalidDestructureError(property.value.name);
('ArrayPattern' === property.value.type || 'ObjectPattern' === property.value.type) && validateDestructuredExports(property.value, exportsToRemove);
}
if ('RestElement' === property.type && 'Identifier' === property.argument.type && exportsToRemove.includes(property.argument.name)) throw invalidDestructureError(property.argument.name);
}
}
}(declaration.id, exportsToRemove), !0)), 0 === declaration.declarations.length && markedForRemoval.add(path);
}
if ((null === (_path_node_declaration1 = path.node.declaration) || void 0 === _path_node_declaration1 ? void 0 : _path_node_declaration1.type) === 'FunctionDeclaration') {
let id = path.node.declaration.id;
id && exportsToRemove.includes(id.name) && markedForRemoval.add(path);
}
if ((null === (_path_node_declaration2 = path.node.declaration) || void 0 === _path_node_declaration2 ? void 0 : _path_node_declaration2.type) === 'ClassDeclaration') {
let id = path.node.declaration.id;
id && exportsToRemove.includes(id.name) && markedForRemoval.add(path);
}
}
'ExportDefaultDeclaration' === path.node.type && exportsToRemove.includes('default') && markedForRemoval.add(path);
}
}), markedForRemoval.size > 0 || exportsFiltered) {
for (let path of markedForRemoval)path.remove();
(0, __WEBPACK_EXTERNAL_MODULE_babel_dead_code_elimination_8901ce62__.deadCodeElimination)(ast, previouslyReferencedIdentifiers);
}
}, transformRoute = (ast)=>{
let hocs = [];
function getHocUid(path, hocName) {
let uid = path.scope.generateUidIdentifier(hocName);
return hocs.push([
hocName,
uid
]), uid;
}
traverse(ast, {
ExportDeclaration (path) {
if (path.isExportDefaultDeclaration()) {
let declaration = path.get('declaration'), expr = declaration.isExpression() ? declaration.node : declaration.isFunctionDeclaration() ? toFunctionExpression(declaration.node) : void 0;
if (expr) {
let uid = getHocUid(path, 'withComponentProps');
declaration.replaceWith(__WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.callExpression(uid, [
expr
]));
}
return;
}
if (path.isExportNamedDeclaration()) {
let decl = path.get('declaration');
if (decl.isVariableDeclaration()) {
decl.get('declarations').forEach((varDeclarator)=>{
let id = varDeclarator.get('id'), init = varDeclarator.get('init'), expr = init.node;
if (!expr || !id.isIdentifier()) return;
let { name } = id.node;
if (!isNamedComponentExport(name)) return;
let uid = getHocUid(path, `with${name}Props`);
init.replaceWith(__WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.callExpression(uid, [
expr
]));
});
return;
}
if (decl.isFunctionDeclaration()) {
let { id } = decl.node;
if (!id) return;
let { name } = id;
if (!isNamedComponentExport(name)) return;
let uid = getHocUid(path, `with${name}Props`);
decl.replaceWith(__WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.variableDeclaration('const', [
__WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.variableDeclarator(__WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.identifier(name), __WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.callExpression(uid, [
toFunctionExpression(decl.node)
]))
]));
}
}
}
}), hocs.length > 0 && ast.program.body.unshift(__WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.importDeclaration(hocs.map(([name, identifier])=>__WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.importSpecifier(identifier, __WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.identifier(name))), __WEBPACK_EXTERNAL_MODULE__babel_types_69e65b52__.stringLiteral('virtual/react-router/with-props')));
};
function isNamedComponentExport(name) {
return NAMED_COMPONENT_EXPORTS.includes(name);
}
async function getReactRouterManifestForDev(routes, options, clientStats, context) {
var _clientStats_assetsByChunkName, _clientStats_assetsByChunkName1;
let result = {};
for (let [key, route] of Object.entries(routes)){
let assets = null == clientStats ? void 0 : null === (_clientStats_assetsByChunkName1 = clientStats.assetsByChunkName) || void 0 === _clientStats_assetsByChunkName1 ? void 0 : _clientStats_assetsByChunkName1[route.id], jsAssets = (null == assets ? void 0 : assets.filter((asset)=>asset.endsWith('.js'))) || [], cssAssets = (null == assets ? void 0 : assets.filter((asset)=>asset.endsWith('.css'))) || [], routeFilePath = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(context, route.file), exports = new Set();
try {
let buildResult = await __WEBPACK_EXTERNAL_MODULE_esbuild__.build({
entryPoints: [
routeFilePath
],
bundle: !1,
write: !1,
metafile: !0,
jsx: 'automatic',
format: 'esm',
platform: 'neutral',
loader: JS_LOADERS
}), entryPoint = Object.values(buildResult.metafile.outputs)[0];
(null == entryPoint ? void 0 : entryPoint.exports) && (exports = new Set(entryPoint.exports));
} catch (error) {
console.error(`Failed to analyze route file ${routeFilePath}:`, error);
}
result[key] = {
id: route.id,
parentId: route.parentId,
path: route.path,
index: route.index,
caseSensitive: route.caseSensitive,
module: combineURLs('/', jsAssets[0] || ''),
hasAction: exports.has(SERVER_EXPORTS.action),
hasLoader: exports.has(SERVER_EXPORTS.loader),
hasClientAction: exports.has(CLIENT_EXPORTS.clientAction),
hasClientLoader: exports.has(CLIENT_EXPORTS.clientLoader),
hasErrorBoundary: exports.has(CLIENT_EXPORTS.ErrorBoundary),
imports: jsAssets.map((asset)=>combineURLs('/', asset)),
css: cssAssets.map((asset)=>combineURLs('/', asset))
};
}
let entryAssets = null == clientStats ? void 0 : null === (_clientStats_assetsByChunkName = clientStats.assetsByChunkName) || void 0 === _clientStats_assetsByChunkName ? void 0 : _clientStats_assetsByChunkName['entry.client'], entryJsAssets = (null == entryAssets ? void 0 : entryAssets.filter((asset)=>asset.endsWith('.js'))) || [], entryCssAssets = (null == entryAssets ? void 0 : entryAssets.filter((asset)=>asset.endsWith('.css'))) || [];
return {
version: String(Math.random()),
url: '/static/js/virtual/react-router/browser-manifest.js',
entry: {
module: combineURLs('/', entryJsAssets[0] || ''),
imports: entryJsAssets.map((asset)=>combineURLs('/', asset)),
css: entryCssAssets.map((asset)=>combineURLs('/', asset))
},
routes: result
};
}
async function transformRouteFederation(args) {
var _args_environment;
let code = args.code, defaultExportMatch = code.match(/\n\s{0,}([\w\d_]+)\sas default,?/);
defaultExportMatch && 'number' == typeof defaultExportMatch.index && (code = code.slice(0, defaultExportMatch.index) + code.slice(defaultExportMatch.index + defaultExportMatch[0].length) + `\nexport default ${defaultExportMatch[1]};`);
let ast = (0, __WEBPACK_EXTERNAL_MODULE__babel_parser_31177a12__.parse)(code, {
sourceType: 'module',
plugins: [
"typescript",
'jsx'
]
});
args.environment && 'web' === args.environment.name && removeExports(ast, [
...SERVER_ONLY_ROUTE_EXPORTS
]), transformRoute(ast);
let transformedCode = generate(ast, {
sourceMaps: !0,
filename: args.resource,
sourceFileName: args.resourcePath,
retainLines: !0,
compact: !1,
concise: !1
}).code, output = (await __WEBPACK_EXTERNAL_MODULE_esbuild__.build({
bundle: !1,
write: !1,
metafile: !0,
jsx: 'automatic',
format: 'esm',
platform: 'neutral',
loader: {
'.ts': 'ts',
'.tsx': 'tsx'
},
stdin: {
contents: transformedCode,
resolveDir: args.context || void 0,
sourcefile: args.resourcePath
}
})).metafile.outputs['stdin.js'];
return (null === (_args_environment = args.environment) || void 0 === _args_environment ? void 0 : _args_environment.name) === 'node' ? `
let cache;
const loadRoute = async (exportName)=>{
if(cache !== undefined) {
return cache[exportName];
}
let exp = await import('${args.resourcePath}?react-router-route');
cache = exp;
return exp[exportName]
}
${output.exports.map((exp)=>'default' === exp ? "export default (...args) => loadRoute(\"default\").then(fn => typeof fn === 'function' ? fn(...args) : fn);" : `export const ${exp} = (...args) => loadRoute(${JSON.stringify(exp)}).then(fn => typeof fn === 'function' ? fn(...args) : fn);`).join('\n')}
` : `const moduleProxy = await import('${args.resourcePath}?react-router-route');
${output.exports.includes('default') ? `const { default: defaultExport, ${output.exports.filter((exp)=>'default' !== exp).join(', ')} } = moduleProxy;` : `const { ${output.exports.join(', ')} } = moduleProxy;`}
export { ${output.exports.map((exp)=>'default' === exp ? 'defaultExport as default' : exp).join(', ')} };
`;
}
var src_rslib_entry_dirname = __webpack_dirname__(__webpack_fileURLToPath__(import.meta.url));
let pluginReactRouter = (options = {})=>({
name: 'rsbuild:react-router',
async setup (api) {
var options1;
let clientStats;
let pluginOptions = {
customServer: !1,
serverOutput: 'module',
...options
};
'commonjs' === pluginOptions.serverOutput && api.processAssets({
stage: 'additional',
targets: [
'node'
]
}, async ({ compilation })=>{
let { RawSource } = compilation.compiler.webpack.sources, packageJsonPath = 'package.json', source = new RawSource(JSON.stringify({
type: 'commonjs'
}));
compilation.getAsset(packageJsonPath) ? compilation.updateAsset(packageJsonPath, source) : compilation.emitAsset(packageJsonPath, source);
}), api.onBeforeStartDevServer(async ()=>{
let { $ } = await import("execa");
$`npx --yes react-router typegen --watch`;
}), api.onBeforeBuild(async ()=>{
let { $ } = await import("execa");
$`npx --yes react-router typegen`;
});
let jiti = (0, __WEBPACK_EXTERNAL_MODULE_jiti__.createJiti)(process.cwd()), { appDirectory = 'app', basename = '/', buildDirectory = 'build', ssr = !0 } = await jiti.import('./react-router.config.ts', {
default: !0
}).catch(()=>(console.error('No react-router.config.ts found, using default configuration.'), {})), routesPath = findEntryFile((0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(appDirectory, 'routes')), routeConfig = await jiti.import(routesPath, {
default: !0
}).catch((error)=>(console.error('Failed to load routes file:', error), console.error('No routes file found in app directory.'), [])), entryClientPath = findEntryFile((0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(appDirectory, 'entry.client')), entryServerPath = findEntryFile((0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(appDirectory, 'entry.server')), serverAppPath = findEntryFile((0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(appDirectory, '../server/index')), hasServerApp = (0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(serverAppPath), templateDir = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(src_rslib_entry_dirname, 'templates'), templateClientPath = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(templateDir, 'entry.client.js'), templateServerPath = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(templateDir, 'entry.server.js'), finalEntryClientPath = (0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(entryClientPath) ? entryClientPath : templateClientPath, finalEntryServerPath = (0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(entryServerPath) ? entryServerPath : templateServerPath, routes = {
root: {
path: '',
id: 'root',
file: (0, __WEBPACK_EXTERNAL_MODULE_pathe__.relative)(appDirectory, (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(appDirectory, 'root.tsx'))
},
...function(appDirectory, routes, rootId = 'root') {
let routeManifest = {};
for (let route of routes)!function walk(route, parentId) {
var file;
let id = route.id || (file = route.file, (0, __WEBPACK_EXTERNAL_MODULE_pathe__.normalize)(file.replace(/\.[^/.]+$/, ''))), manifestItem = {
id,
parentId,
file: (0, __WEBPACK_EXTERNAL_MODULE_pathe__.isAbsolute)(route.file) ? (0, __WEBPACK_EXTERNAL_MODULE_pathe__.relative)(appDirectory, route.file) : route.file,
path: route.path,
index: route.index,
caseSensitive: route.caseSensitive
};
if (Object.prototype.hasOwnProperty.call(routeManifest, id)) throw Error(`Unable to define routes with duplicate route id: "${id}"`);
if (routeManifest[id] = manifestItem, route.children) for (let child of route.children)walk(child, id);
}(route, rootId);
return routeManifest;
}(appDirectory, routeConfig)
}, outputClientPath = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(buildDirectory, 'client'), assetsBuildDirectory = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.relative)(process.cwd(), outputClientPath);
api.onAfterEnvironmentCompile(({ stats, environment })=>{
if ('web' === environment.name && (clientStats = null == stats ? void 0 : stats.toJson()), pluginOptions.federation && ssr) {
let serverBuildDir = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(buildDirectory, 'server'), clientBuildDir = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(buildDirectory, 'client');
if ((0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(serverBuildDir)) {
let ssrDir = (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(clientBuildDir, 'static');
(0, __WEBPACK_EXTERNAL_MODULE_fs_extra_ce68a66b__.copySync)(serverBuildDir, ssrDir);
}
}
});
let vmodPlugin = new __WEBPACK_EXTERNAL_MODULE_rspack_plugin_virtual_module_609978fd__.RspackVirtualModulePlugin({
'virtual/react-router/browser-manifest': 'export default {};',
'virtual/react-router/server-manifest': 'export default {};',
'virtual/react-router/server-build': (options1 = {
entryServerPath: finalEntryServerPath,
assetsBuildDirectory,
basename,
appDirectory,
ssr,
federation: options.federation
}).federation ? `
// Create a module cache to store the dynamically imported module
let entryServerModule = null;
// Function to ensure the module is loaded
const ensureEntryServerLoaded = async () => {
if (!entryServerModule) {
entryServerModule = await import(${JSON.stringify(options1.entryServerPath)});
}
return entryServerModule;
};
// Helper function to create async handlers
const createAsyncHandler = (exportName) => {
return async (...args) => {
const module = await ensureEntryServerLoaded();
const handler = module[exportName];
return typeof handler === 'function' ? handler(...args) : handler;
};
};
// Helper function to create sync handlers
const createSyncHandler = (exportName) => {
return (...args) => {
if (!entryServerModule) {
throw new Error('Entry server module not loaded yet. Call an async method first or await ensureEntryServerLoaded()');
}
const handler = entryServerModule[exportName];
return typeof handler === 'function' ? handler(...args) : handler;
};
};
// Create a proxy for the entryServer exports
const entryServer = new Proxy({}, {
get: (target, prop) => {
if (entryServerModule) {
return entryServerModule[prop];
}
if (prop === 'handleDataRequest' || prop === 'handleRequest' || prop === 'default') {
return createAsyncHandler(prop);
}
}
});
// Preload the entry server module
ensureEntryServerLoaded().catch(console.error);
${Object.keys(routes).map((key, index)=>{
let route = routes[key];
return `import * as route${index} from ${JSON.stringify(`${(0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(options1.appDirectory, route.file)}?react-router-route`)};`;
}).join('\n')}
export { default as assets } from "virtual/react-router/server-manifest";
export const assetsBuildDirectory = ${JSON.stringify(options1.assetsBuildDirectory)};
export const basename = ${JSON.stringify(options1.basename)};
export const future = ${JSON.stringify({})};
export const isSpaMode = ${!options1.ssr};
export const ssr = ${options1.ssr};
export const publicPath = "/";
export const prerender = [];
export const entry = { module: entryServer };
export const routes = {
${Object.keys(routes).map((key, index)=>{
let route = routes[key];
return `${JSON.stringify(key)}: {
id: ${JSON.stringify(route.id)},
parentId: ${JSON.stringify(route.parentId)},
path: ${JSON.stringify(route.path)},
index: ${JSON.stringify(route.index)},
caseSensitive: ${JSON.stringify(route.caseSensitive)},
module: route${index}
}
`;
}).join(',\n ')}
};
` : `
import * as entryServer from ${JSON.stringify(options1.entryServerPath)};
${Object.keys(routes).map((key, index)=>{
let route = routes[key];
return `import * as route${index} from ${JSON.stringify(`${(0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(options1.appDirectory, route.file)}?react-router-route`)};`;
}).join('\n')}
export { default as assets } from "virtual/react-router/server-manifest";
export const assetsBuildDirectory = ${JSON.stringify(options1.assetsBuildDirectory)};
export const basename = ${JSON.stringify(options1.basename)};
export const future = ${JSON.stringify({})};
export const isSpaMode = ${!options1.ssr};
export const ssr = ${options1.ssr};
export const prerender = [];
export const publicPath = "/";
export const entry = { module: entryServer };
export const routes = {
${Object.keys(routes).map((key, index)=>{
let route = routes[key];
return `${JSON.stringify(key)}: {
id: ${JSON.stringify(route.id)},
parentId: ${JSON.stringify(route.parentId)},
path: ${JSON.stringify(route.path)},
index: ${JSON.stringify(route.index)},
caseSensitive: ${JSON.stringify(route.caseSensitive)},
module: route${index}
}
`;
}).join(',\n ')}
};
`,
'virtual/react-router/with-props': `
import { createElement as h } from "react";
import { useActionData, useLoaderData, useMatches, useParams, useRouteError } from "react-router";
export function withComponentProps(Component) {
return function Wrapped() {
const props = {
params: useParams(),
loaderData: useLoaderData(),
actionData: useActionData(),
matches: useMatches(),
};
return h(Component, props);
};
}
export function withHydrateFallbackProps(HydrateFallback) {
return function Wrapped() {
const props = {
params: useParams(),
};
return h(HydrateFallback, props);
};
}
export function withErrorBoundaryProps(ErrorBoundary) {
return function Wrapped() {
const props = {
params: useParams(),
loaderData: useLoaderData(),
actionData: useActionData(),
error: useRouteError(),
};
return h(ErrorBoundary, props);
};
}
`
});
api.modifyRsbuildConfig(async (config, { mergeRsbuildConfig })=>{
var _config_output, _config_environments_node_output, _config_environments_node, _config_environments;
return mergeRsbuildConfig(config, {
output: {
assetPrefix: (null === (_config_output = config.output) || void 0 === _config_output ? void 0 : _config_output.assetPrefix) || '/'
},
dev: {
writeToDisk: !0,
hmr: !1,
liveReload: !0,
setupMiddlewares: pluginOptions.customServer ? [] : [
(middlewares, server)=>{
middlewares.push(createDevServerMiddleware(server));
}
]
},
tools: {
rspack: {
plugins: [
vmodPlugin
]
}
},
environments: {
web: {
source: {
entry: {
'entry.client': finalEntryClientPath + (options.federation ? '?react-router-route-federation' : ''),
'virtual/react-router/browser-manifest': 'virtual/react-router/browser-manifest',
...Object.values(routes).reduce((acc, route)=>(acc[route.file.slice(0, route.file.lastIndexOf('.'))] = {
import: `${(0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(appDirectory, route.file)}?${options.federation ? 'react-router-route-federation' : 'react-router-route'}`
}, acc), {})
}
},
output: {
filename: {
js: '[name].js'
},
distPath: {
root: outputClientPath
}
},
tools: {
rspack: {
name: 'web',
experiments: {
topLevelAwait: !0,
outputModule: !0
},
externalsType: 'module',
output: {
chunkFormat: 'module',
chunkLoading: 'import',
workerChunkLoading: 'import',
wasmLoading: 'fetch',
library: {
type: 'module'
},
module: !0
},
optimization: {
runtimeChunk: 'single'
}
}
}
},
node: {
source: {
entry: {
...hasServerApp ? {
app: serverAppPath + (options.federation ? '?react-router-route-federation' : '')
} : {
app: 'virtual/react-router/server-build' + (options.federation ? '?react-router-route-federation' : '')
},
'entry.server': finalEntryServerPath + (options.federation ? '?react-router-route-federation' : '')
}
},
output: {
distPath: {
root: (0, __WEBPACK_EXTERNAL_MODULE_pathe__.resolve)(buildDirectory, 'server')
},
target: (null === (_config_environments = config.environments) || void 0 === _config_environments ? void 0 : null === (_config_environments_node = _config_environments.node) || void 0 === _config_environments_node ? void 0 : null === (_config_environments_node_output = _config_environments_node.output) || void 0 === _config_environments_node_output ? void 0 : _config_environments_node_output.target) || 'node',
filename: {
js: 'static/js/[name].js'
}
},
tools: {
rspack: {
target: options.federation ? 'async-node' : 'node',
externals: [
'express'
],
dependencies: [
'web'
],
experiments: {
outputModule: 'module' === pluginOptions.serverOutput
},
externalsType: pluginOptions.serverOutput,
output: {
chunkFormat: pluginOptions.serverOutput,
chunkLoading: 'module' === pluginOptions.serverOutput ? 'import' : options.federation ? 'async-node' : 'require',
workerChunkLoading: 'module' === pluginOptions.serverOutput ? 'import' : 'require',
wasmLoading: 'fetch',
library: {
type: pluginOptions.serverOutput
},
module: 'module' === pluginOptions.serverOutput
}
}
}
}
}
});
}), api.modifyEnvironmentConfig(async (config, { name, mergeEnvironmentConfig })=>'web' === name ? mergeEnvironmentConfig(config, {
tools: {
rspack: (rspackConfig)=>{
if (rspackConfig.plugins) rspackConfig.plugins.push({
apply (compiler) {
compiler.hooks.emit.tapAsync('ModifyBrowserManifest', async (compilation, callback)=>{
let manifest = await getReactRouterManifestForDev(routes, pluginOptions, compilation.getStats().toJson(), appDirectory), manifestPath = 'static/js/virtual/react-router/browser-manifest.js';
if (compilation.assets[manifestPath]) {
let newSource = compilation.assets[manifestPath].source().toString().replace(/["'`]PLACEHOLDER["'`]/, (0, __WEBPACK_EXTERNAL_MODULE_jsesc__.default)(manifest, {
es6: !0
}));
compilation.assets[manifestPath] = {
source: ()=>newSource,
size: ()=>newSource.length,
map: ()=>({
version: 3,
sources: [
manifestPath
],
names: [],
mappings: '',
file: manifestPath,
sourcesContent: [
newSource
]
}),
sourceAndMap: ()=>({
source: newSource,
map: {
version: 3,
sources: [
manifestPath
],
names: [],
mappings: '',
file: manifestPath,
sourcesContent: [
newSource
]
}
}),
updateHash: (hash)=>hash.update(newSource),
buffer: ()=>Buffer.from(newSource)
};
}
callback();
});
}
});
return rspackConfig;
}
}
}) : config), api.processAssets({
stage: 'additional',
targets: [
'node'
]
}, ({ sources, compilation })=>{
let packageJsonPath = 'package.json', source = new sources.RawSource(`{"type": "${pluginOptions.serverOutput}"}`);
compilation.getAsset(packageJsonPath) ? compilation.updateAsset(packageJsonPath, source) : compilation.emitAsset(packageJsonPath, source);
}), api.transform({
test: /virtual\/react-router\/(browser|server)-manifest/
}, async (args)=>{
if ('web' === args.environment.name) return {
code: 'window.__reactRouterManifest = "PLACEHOLDER";'
};
let manifest = await getReactRouterManifestForDev(routes, pluginOptions, clientStats, appDirectory);
return {
code: `export default ${(0, __WEBPACK_EXTERNAL_MODULE_jsesc__.default)(manifest, {
es6: !0
})};`
};
}), api.transform({
resourceQuery: /\?react-router-route-federation/
}, async (args)=>await transformRouteFederation(args)), api.transform({
resourceQuery: /\?react-router-route/
}, async (args)=>{
let code;
try {
code = (await __WEBPACK_EXTERNAL_MODULE_esbuild__.transform(args.code, {
jsx: 'automatic',
format: 'esm',
platform: 'neutral',
loader: args.resourcePath.endsWith('x') ? 'tsx' : 'ts'
})).code;
} catch (error) {
throw console.error(args.resourcePath), error;
}
let defaultExportMatch = code.match(/\n\s{0,}([\w\d_]+)\sas default,?/);
defaultExportMatch && 'number' == typeof defaultExportMatch.index && (code = code.slice(0, defaultExportMatch.index) + code.slice(defaultExportMatch.index + defaultExportMatch[0].length) + `\nexport default ${defaultExportMatch[1]};`);
let ast = (0, __WEBPACK_EXTERNAL_MODULE__babel_parser_31177a12__.parse)(code, {
sourceType: 'module'
});
return 'web' === args.environment.name && removeExports(ast, [
...SERVER_ONLY_ROUTE_EXPORTS
]), transformRoute(ast), generate(ast, {
sourceMaps: !0,
filename: args.resource,
sourceFileName: args.resourcePath
});
});
}
});
export { pluginReactRouter };