rsbuild-plugin-react-router 0.6.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/511.js +10 -3
- package/dist/environment-output.d.ts +16 -2
- package/dist/index.cjs +110 -74
- package/dist/index.js +109 -81
- package/dist/manifest.d.ts +2 -0
- package/dist/mode-plan.d.ts +2 -1
- package/dist/plugin-utils.d.ts +19 -13
- package/dist/rsc-virtual-modules.d.ts +4 -4
- package/dist/templates/entry.rsc.js +2 -2
- package/package.json +1 -1
- package/src/environment-output.ts +50 -1
- package/src/index.ts +44 -61
- package/src/manifest.ts +26 -20
- package/src/mode-plan.ts +11 -13
- package/src/modify-browser-manifest.ts +4 -4
- package/src/plugin-utils.ts +37 -23
- package/src/rsc-route-transforms.ts +8 -12
- package/src/rsc-runtime.d.ts +11 -0
- package/src/rsc-virtual-modules.ts +62 -9
- package/src/templates/entry.rsc.tsx +1 -1
package/README.md
CHANGED
|
@@ -343,6 +343,28 @@ If you configure `output.assetPrefix` in Rsbuild, the plugin uses that value
|
|
|
343
343
|
for the React Router browser manifest and server build `publicPath` so asset
|
|
344
344
|
URLs resolve correctly when serving from a CDN or sub-path.
|
|
345
345
|
|
|
346
|
+
The web environment's own `output.assetPrefix` is passed through to the browser
|
|
347
|
+
compiler untouched, so `environments.web.output.assetPrefix: 'auto'` lets the
|
|
348
|
+
browser runtime resolve async chunks and stylesheets relative to the loaded
|
|
349
|
+
script. The server build and browser manifest need an absolute prefix: they use
|
|
350
|
+
the web environment's prefix when it is usable and otherwise fall back to the
|
|
351
|
+
root `output.assetPrefix`. A common CDN setup is therefore:
|
|
352
|
+
|
|
353
|
+
```ts
|
|
354
|
+
export default defineConfig({
|
|
355
|
+
output: { assetPrefix: 'https://cdn.example.com/app/' }, // server-rendered URLs
|
|
356
|
+
environments: {
|
|
357
|
+
web: { output: { assetPrefix: 'auto' } }, // browser runtime resolves itself
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
The plugin does not set `output.filename`, `chunkFilename`, or `publicPath`
|
|
363
|
+
for the web environment. Production browser entries use Rsbuild's default
|
|
364
|
+
content-hashed filenames, and `output.filename`, `output.filenameHash`,
|
|
365
|
+
`output.distPath`, and `tools.rspack` output settings you configure govern
|
|
366
|
+
the emitted files and the manifest URLs that reference them.
|
|
367
|
+
|
|
346
368
|
## Custom Server Setup
|
|
347
369
|
|
|
348
370
|
The plugin supports two ways to handle server-side rendering:
|
|
@@ -465,6 +487,29 @@ and every configured bundle are
|
|
|
465
487
|
evaluated and published as one generation; one failing bundle keeps the whole
|
|
466
488
|
previous generation active.
|
|
467
489
|
|
|
490
|
+
### Sharing `createContext()` instances with a custom server
|
|
491
|
+
|
|
492
|
+
React Router middleware contexts are matched by identity, so a custom server's
|
|
493
|
+
`getLoadContext` must use the same `createContext()` instance the routes import.
|
|
494
|
+
With a bundled server build that instance lives inside the build. Re-export it
|
|
495
|
+
from `app/entry.server.tsx` and read it from `build.entry.module`:
|
|
496
|
+
|
|
497
|
+
```ts
|
|
498
|
+
// app/entry.server.tsx
|
|
499
|
+
export { valueContext } from './context';
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
```js
|
|
503
|
+
// server.js
|
|
504
|
+
getLoadContext: async () => {
|
|
505
|
+
const { valueContext } = (await build()).entry.module;
|
|
506
|
+
return new RouterContextProvider([[valueContext, 'value']]);
|
|
507
|
+
},
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
This works in development through `loadReactRouterServerBuild` and in
|
|
511
|
+
production through `resolveReactRouterServerBuild`.
|
|
512
|
+
|
|
468
513
|
`resolveReactRouterServerBuild` accepts an imported production server module,
|
|
469
514
|
normalizes ESM and CommonJS namespace shapes, resolves supported asynchronous
|
|
470
515
|
build exports, and validates the result before it reaches React Router.
|
package/dist/511.js
CHANGED
|
@@ -375,9 +375,16 @@ function combineURLs(baseURL, relativeURL) {
|
|
|
375
375
|
function normalizeAssetPrefix(assetPrefix) {
|
|
376
376
|
return assetPrefix && 'auto' !== assetPrefix ? assetPrefix.endsWith('/') ? assetPrefix : `${assetPrefix}/` : '/';
|
|
377
377
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
378
|
+
let asString = (value)=>'string' == typeof value ? value : void 0, pickConfiguredAssetPrefix = ({ dev, output }, isBuild)=>isBuild ? asString(output?.assetPrefix) : asString(dev?.assetPrefix) ?? asString(output?.assetPrefix);
|
|
379
|
+
function resolveEffectiveAssetPrefix(config, ...fallbacks) {
|
|
380
|
+
for (let candidate of [
|
|
381
|
+
config,
|
|
382
|
+
...fallbacks
|
|
383
|
+
]){
|
|
384
|
+
let prefix = pickConfiguredAssetPrefix(candidate, config.isBuild);
|
|
385
|
+
if (prefix && 'auto' !== prefix) return normalizeAssetPrefix(prefix);
|
|
386
|
+
}
|
|
387
|
+
return '/';
|
|
381
388
|
}
|
|
382
389
|
function createRouteId(file) {
|
|
383
390
|
return normalize(file.replace(/\.[^/.]+$/, ''));
|
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
import type { RsbuildPluginAPI } from '@rsbuild/core';
|
|
2
|
-
|
|
1
|
+
import type { RsbuildPluginAPI, Rspack } from '@rsbuild/core';
|
|
2
|
+
/**
|
|
3
|
+
* Rspack `output` policy for the web and node environments, in two tiers:
|
|
4
|
+
*
|
|
5
|
+
* 1. Overridable defaults, registered through `modifyRspackConfig`. Rsbuild
|
|
6
|
+
* runs the user's `tools.rspack` (object or function form) after this hook,
|
|
7
|
+
* so user output settings such as `chunkFilename` take precedence
|
|
8
|
+
* (#129, #130). Neither `filename` nor `publicPath` is set here: Rsbuild
|
|
9
|
+
* derives them from `output.filename`/`output.filenameHash`/`output.distPath`
|
|
10
|
+
* and the environment's `output.assetPrefix`, which keeps `'auto'` intact.
|
|
11
|
+
* 2. Enforced invariants, registered through a `tools.rspack` function that
|
|
12
|
+
* runs after the user's own `tools.rspack`: the server library type must
|
|
13
|
+
* match the server module format, and federation builds need async startup.
|
|
14
|
+
*/
|
|
15
|
+
export declare const registerReactRouterEnvironmentOutput: ({ api, federation, resolvedServerOutput, webOutput, }: {
|
|
3
16
|
api: RsbuildPluginAPI;
|
|
4
17
|
federation: boolean | undefined;
|
|
5
18
|
resolvedServerOutput: "commonjs" | "module";
|
|
19
|
+
webOutput: NonNullable<Rspack.Configuration["output"]>;
|
|
6
20
|
}) => void;
|
package/dist/index.cjs
CHANGED
|
@@ -543,9 +543,16 @@ function combineURLs(baseURL, relativeURL) {
|
|
|
543
543
|
function normalizeAssetPrefix(assetPrefix) {
|
|
544
544
|
return assetPrefix && 'auto' !== assetPrefix ? assetPrefix.endsWith('/') ? assetPrefix : `${assetPrefix}/` : '/';
|
|
545
545
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
546
|
+
const asString = (value)=>'string' == typeof value ? value : void 0, pickConfiguredAssetPrefix = ({ dev, output }, isBuild)=>isBuild ? asString(output?.assetPrefix) : asString(dev?.assetPrefix) ?? asString(output?.assetPrefix);
|
|
547
|
+
function resolveEffectiveAssetPrefix(config, ...fallbacks) {
|
|
548
|
+
for (let candidate of [
|
|
549
|
+
config,
|
|
550
|
+
...fallbacks
|
|
551
|
+
]){
|
|
552
|
+
let prefix = pickConfiguredAssetPrefix(candidate, config.isBuild);
|
|
553
|
+
if (prefix && 'auto' !== prefix) return normalizeAssetPrefix(prefix);
|
|
554
|
+
}
|
|
555
|
+
return '/';
|
|
549
556
|
}
|
|
550
557
|
function createRouteId(file) {
|
|
551
558
|
return (0, external_pathe_namespaceObject.normalize)(file.replace(/\.[^/.]+$/, ''));
|
|
@@ -619,8 +626,27 @@ const resolveEntryWithTemplate = ({ appDirectory, entryName, templateName, templ
|
|
|
619
626
|
asyncStartup: !0
|
|
620
627
|
});
|
|
621
628
|
}
|
|
622
|
-
}, registerReactRouterEnvironmentOutput = ({ api, federation, resolvedServerOutput })=>{
|
|
623
|
-
|
|
629
|
+
}, registerReactRouterEnvironmentOutput = ({ api, federation, resolvedServerOutput, webOutput })=>{
|
|
630
|
+
let nodeChunkLoading = 'module' === resolvedServerOutput ? 'import' : federation ? 'async-node' : 'require';
|
|
631
|
+
api.modifyRspackConfig((rspackConfig, { environment, mergeConfig })=>'web' === environment.name ? mergeConfig(rspackConfig, {
|
|
632
|
+
output: {
|
|
633
|
+
...webOutput,
|
|
634
|
+
...federation ? {
|
|
635
|
+
chunkLoading: 'import'
|
|
636
|
+
} : {}
|
|
637
|
+
}
|
|
638
|
+
}) : 'node' === environment.name ? mergeConfig(rspackConfig, {
|
|
639
|
+
output: {
|
|
640
|
+
chunkFormat: resolvedServerOutput,
|
|
641
|
+
chunkLoading: nodeChunkLoading,
|
|
642
|
+
devtoolModuleFilenameTemplate: '[absolute-resource-path]',
|
|
643
|
+
devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]',
|
|
644
|
+
workerChunkLoading: nodeChunkLoading,
|
|
645
|
+
wasmLoading: 'fetch',
|
|
646
|
+
module: 'module' === resolvedServerOutput,
|
|
647
|
+
chunkFilename: 'static/js/async/[name].js'
|
|
648
|
+
}
|
|
649
|
+
}) : rspackConfig), api.modifyEnvironmentConfig(async (config, { name, mergeEnvironmentConfig })=>'web' !== name && 'node' !== name ? config : mergeEnvironmentConfig(config, {
|
|
624
650
|
tools: {
|
|
625
651
|
rspack: (rspackConfig)=>{
|
|
626
652
|
if (federation && ensureFederationAsyncStartup(rspackConfig), 'node' === name) {
|
|
@@ -11790,14 +11816,7 @@ const createReactRouterManifestOptions = ({ routeChunks, routeModuleAnalysis })=
|
|
|
11790
11816
|
routeModuleAnalysis
|
|
11791
11817
|
} : {}
|
|
11792
11818
|
};
|
|
11793
|
-
},
|
|
11794
|
-
let ownChunkAsset = `${chunkName}.js`, ownFileIndex = files.findIndex((file)=>file.endsWith(ownChunkAsset));
|
|
11795
|
-
return ownFileIndex <= 0 ? files : [
|
|
11796
|
-
files[ownFileIndex],
|
|
11797
|
-
...files.slice(0, ownFileIndex),
|
|
11798
|
-
...files.slice(ownFileIndex + 1)
|
|
11799
|
-
];
|
|
11800
|
-
}, collectManifestFilesByName = (items, names, getFiles)=>{
|
|
11819
|
+
}, isManifestJsAsset = (asset)=>/(?<!\.hot-update)\.[cm]?js(?:\?.*)?$/.test(asset), isManifestCssAsset = (asset)=>/\.css(?:\?.*)?$/.test(asset), collectManifestFilesByName = (items, names, getFiles)=>{
|
|
11801
11820
|
let filesByName = {};
|
|
11802
11821
|
if (!names) {
|
|
11803
11822
|
for (let [name, item] of items)null != item && (filesByName[name] = getFiles(name, item));
|
|
@@ -11813,14 +11832,14 @@ const createReactRouterManifestOptions = ({ routeChunks, routeModuleAnalysis })=
|
|
|
11813
11832
|
return filesByName;
|
|
11814
11833
|
}, createReactRouterManifestStats = (compilation, chunkNames)=>{
|
|
11815
11834
|
if (!compilation) return;
|
|
11816
|
-
let assetsByChunkName = collectManifestFilesByName(compilation.namedChunks, chunkNames, (
|
|
11835
|
+
let assetsByChunkName = collectManifestFilesByName(compilation.namedChunks, chunkNames, (_chunkName, chunk)=>Array.from(chunk.files ?? [])), entrypointFilesByName = compilation.entrypoints ? collectManifestFilesByName(compilation.entrypoints, chunkNames, (_name, entrypoint)=>Array.from(entrypoint.getFiles?.() ?? [])) : {};
|
|
11817
11836
|
return Object.keys(entrypointFilesByName).length > 0 ? {
|
|
11818
11837
|
assetsByChunkName,
|
|
11819
11838
|
entrypointFilesByName
|
|
11820
11839
|
} : {
|
|
11821
11840
|
assetsByChunkName
|
|
11822
11841
|
};
|
|
11823
|
-
}, DEFAULT_MANIFEST_DIR =
|
|
11842
|
+
}, DEFAULT_MANIFEST_DIR = 'static/js', CSS_IMPORT_RE = /\.(?:css|less|sass|scss)(?:\?[^'"`]+)?['"`]/, createChunkAssetResolver = (clientStats, includeEntrypointJs)=>{
|
|
11824
11843
|
let chunkAssetsByName = new Map();
|
|
11825
11844
|
return (chunkName)=>{
|
|
11826
11845
|
let cached = chunkAssetsByName.get(chunkName);
|
|
@@ -11829,16 +11848,16 @@ const createReactRouterManifestOptions = ({ routeChunks, routeModuleAnalysis })=
|
|
|
11829
11848
|
if (!assets) {
|
|
11830
11849
|
let result = {
|
|
11831
11850
|
js: [
|
|
11832
|
-
`${
|
|
11851
|
+
`${DEFAULT_MANIFEST_DIR}/${chunkName}.js`
|
|
11833
11852
|
],
|
|
11834
11853
|
css: []
|
|
11835
11854
|
};
|
|
11836
11855
|
return chunkAssetsByName.set(chunkName, result), result;
|
|
11837
11856
|
}
|
|
11838
11857
|
let cssAssets = new Set(), jsAssets = new Set();
|
|
11839
|
-
for (let asset of assets)asset
|
|
11840
|
-
for (let asset of clientStats?.entrypointFilesByName?.[chunkName] ?? [])asset
|
|
11841
|
-
0 === jsAssets.size
|
|
11858
|
+
for (let asset of assets)isManifestCssAsset(asset) ? cssAssets.add(asset) : isManifestJsAsset(asset) && jsAssets.add(asset);
|
|
11859
|
+
for (let asset of clientStats?.entrypointFilesByName?.[chunkName] ?? [])isManifestCssAsset(asset) ? cssAssets.add(asset) : includeEntrypointJs && isManifestJsAsset(asset) && jsAssets.add(asset);
|
|
11860
|
+
if (0 === jsAssets.size) throw Error(`[react-router] Chunk "${chunkName}" emitted no JavaScript asset the browser manifest can reference (files: ${assets.join(', ') || 'none'}). Check the web \`output.filename.js\` scheme.`);
|
|
11842
11861
|
let result = {
|
|
11843
11862
|
js: [
|
|
11844
11863
|
...jsAssets
|
|
@@ -11851,7 +11870,7 @@ const createReactRouterManifestOptions = ({ routeChunks, routeModuleAnalysis })=
|
|
|
11851
11870
|
};
|
|
11852
11871
|
}, analyzeRouteForManifestEffect = ({ discoveredCssAssets, isBuild, routeChunkCache, routeChunkConfig, routeEntryName, routeFilePath, route, routeModuleAnalysis })=>tryPluginPromise(async ()=>{
|
|
11853
11872
|
let { code, exports: exportNames } = await routeModuleAnalysis?.(routeFilePath, route) ?? await getRouteModuleAnalysis(routeFilePath), cssAssets = !isBuild && 0 === discoveredCssAssets.length && CSS_IMPORT_RE.test(code) ? [
|
|
11854
|
-
`${
|
|
11873
|
+
`${DEFAULT_MANIFEST_DIR.replace('/js', '/css')}/${routeEntryName}.css`
|
|
11855
11874
|
] : discoveredCssAssets, chunkInfo = isBuild && routeChunkConfig ? await detectRouteChunksIfEnabled(routeChunkCache, routeChunkConfig, routeFilePath, code) : null;
|
|
11856
11875
|
return {
|
|
11857
11876
|
cssAssets,
|
|
@@ -11865,9 +11884,9 @@ const createReactRouterManifestOptions = ({ routeChunks, routeModuleAnalysis })=
|
|
|
11865
11884
|
routeModuleExports: [],
|
|
11866
11885
|
hasRouteChunkByExportName: null
|
|
11867
11886
|
})))), getManifestDirFromEntryAsset = (entryModulePath)=>{
|
|
11868
|
-
if (!entryModulePath) return
|
|
11887
|
+
if (!entryModulePath) return DEFAULT_MANIFEST_DIR;
|
|
11869
11888
|
let dir = (0, external_pathe_namespaceObject.dirname)(entryModulePath);
|
|
11870
|
-
return '.' === dir ?
|
|
11889
|
+
return '.' === dir ? DEFAULT_MANIFEST_DIR : dir;
|
|
11871
11890
|
}, getReactRouterManifestPath = ({ version, isBuild, entryModulePath })=>{
|
|
11872
11891
|
if (!isBuild) return 'static/js/virtual/react-router/browser-manifest.js';
|
|
11873
11892
|
let dir = getManifestDirFromEntryAsset(entryModulePath);
|
|
@@ -12418,13 +12437,13 @@ const redirectStatusCodes = new Set([
|
|
|
12418
12437
|
}), external_jsesc_namespaceObject = require("jsesc");
|
|
12419
12438
|
var external_jsesc_default = __webpack_require__.n(external_jsesc_namespaceObject);
|
|
12420
12439
|
const BROWSER_MANIFEST_ASSET = 'static/js/virtual/react-router/browser-manifest.js', ABSOLUTE_URL_RE = /^[a-zA-Z][a-zA-Z\d+\-.]*:/, toManifestAssetUrl = (assetPrefix, assetName)=>ABSOLUTE_URL_RE.test(assetName) || assetName.startsWith('//') || assetName.startsWith('/') ? assetName : combineURLs(assetPrefix, assetName), addIntegrity = (sri, assetPrefix, assetName, integrity)=>{
|
|
12421
|
-
'string' == typeof assetName && assetName
|
|
12440
|
+
'string' == typeof assetName && isManifestJsAsset(assetName) && 'string' == typeof integrity && (sri[toManifestAssetUrl(assetPrefix, assetName)] = integrity);
|
|
12422
12441
|
}, computeSubresourceIntegrity = (source)=>{
|
|
12423
12442
|
if (source) return `sha384-${(0, external_node_crypto_namespaceObject.createHash)('sha384').update(source.source()).digest('base64')}`;
|
|
12424
12443
|
}, collectSubresourceIntegrity = (stats, compilation, assetPrefix = '/')=>{
|
|
12425
12444
|
let sri = {};
|
|
12426
12445
|
for (let asset of stats?.assets ?? [])addIntegrity(sri, assetPrefix, asset.name, asset.integrity);
|
|
12427
|
-
if ('function' == typeof compilation?.getAssets) for (let asset of compilation.getAssets())asset.name
|
|
12446
|
+
if ('function' == typeof compilation?.getAssets) for (let asset of compilation.getAssets())isManifestJsAsset(asset.name) && addIntegrity(sri, assetPrefix, asset.name, computeSubresourceIntegrity(asset.source) ?? asset.info?.integrity);
|
|
12428
12447
|
return Object.keys(sri).length > 0 ? sri : void 0;
|
|
12429
12448
|
};
|
|
12430
12449
|
function registerModifyBrowserManifestAssets(api, routes, pluginOptions, appDirectory, assetPrefix = '/', routeChunkOptions, options) {
|
|
@@ -12444,7 +12463,7 @@ function registerModifyBrowserManifestAssets(api, routes, pluginOptions, appDire
|
|
|
12444
12463
|
compilation.updateAsset(BROWSER_MANIFEST_ASSET, new sources.RawSource(newSource));
|
|
12445
12464
|
}
|
|
12446
12465
|
if (isBuild) {
|
|
12447
|
-
let entryAssets = stats?.assetsByChunkName?.['entry.client'], entryJsAssets = entryAssets?.filter(
|
|
12466
|
+
let entryAssets = stats?.assetsByChunkName?.['entry.client'], entryJsAssets = entryAssets?.filter(isManifestJsAsset) || [], manifestPath = getReactRouterManifestPath({
|
|
12448
12467
|
version: manifest.version,
|
|
12449
12468
|
isBuild: !0,
|
|
12450
12469
|
entryModulePath: entryJsAssets[0]
|
|
@@ -14418,12 +14437,14 @@ export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRoute
|
|
|
14418
14437
|
}, createServerRouteEntry = async (options)=>{
|
|
14419
14438
|
let ast, plan = await createRscRouteExportPlan(options);
|
|
14420
14439
|
validateRscRouteExportPlan(plan, options);
|
|
14421
|
-
let lines = [], needsReactImport = !1, needsEnsureHmrImport = !1, needsStyleEntryImport = !1,
|
|
14440
|
+
let lines = [], needsReactImport = !1, needsEnsureHmrImport = !1, needsStyleEntryImport = !1, pushStylesheetLinks = (entryCssFilesExpression)=>{
|
|
14441
|
+
lines.push(` ...(${entryCssFilesExpression} ?? []).map(href =>`), lines.push(' React.createElement("link", { key: href, rel: "stylesheet", href: href, precedence: "default" })),');
|
|
14442
|
+
}, streamsClientRouteCss = !plan.exportNames.some(isServerComponentExport) && plan.exportNames.includes('default') && programHasSideEffectStyleImports((ast = yuku_parse(options.code, {
|
|
14422
14443
|
sourceType: 'module'
|
|
14423
14444
|
})).program ?? ast);
|
|
14424
14445
|
for (let exportName of plan.exportNames){
|
|
14425
14446
|
if (streamsClientRouteCss && 'default' === exportName) {
|
|
14426
|
-
needsReactImport = !0, needsStyleEntryImport = !0, lines.push(`import RscClientRouteDefault___ from ${JSON.stringify(plan.clientTargetFor('default'))};`), lines.push('export default function RscClientRouteWithStyles___(props) {'), lines.push(' return React.createElement(React.Fragment, null,'),
|
|
14447
|
+
needsReactImport = !0, needsStyleEntryImport = !0, lines.push(`import RscClientRouteDefault___ from ${JSON.stringify(plan.clientTargetFor('default'))};`), lines.push('export default function RscClientRouteWithStyles___(props) {'), lines.push(' return React.createElement(React.Fragment, null,'), pushStylesheetLinks(`${RSC_ROUTE_STYLE_ENTRY_EXPORT}.entryCssFiles`), lines.push(' React.createElement(RscClientRouteDefault___, props),'), lines.push(' );'), lines.push('}');
|
|
14427
14448
|
continue;
|
|
14428
14449
|
}
|
|
14429
14450
|
if (isClientRouteExport(exportName)) {
|
|
@@ -14431,7 +14452,7 @@ export function EnsureClientRouteModuleForHMR___() { return ___EnsureClientRoute
|
|
|
14431
14452
|
continue;
|
|
14432
14453
|
}
|
|
14433
14454
|
if (isServerComponentExport(exportName)) {
|
|
14434
|
-
needsReactImport = !0, needsEnsureHmrImport = !0, lines.push(`import { ${exportName} as ${exportName}WithoutClientChunk } from ${JSON.stringify(plan.serverTarget)};`), lines.push(`export function ${exportName}(props) {`), lines.push(' return React.createElement(React.Fragment, null,'),
|
|
14455
|
+
needsReactImport = !0, needsEnsureHmrImport = !0, lines.push(`import { ${exportName} as ${exportName}WithoutClientChunk } from ${JSON.stringify(plan.serverTarget)};`), lines.push(`export function ${exportName}(props) {`), lines.push(' return React.createElement(React.Fragment, null,'), pushStylesheetLinks(`${exportName}WithoutClientChunk.entryCssFiles`), lines.push(' React.createElement(EnsureClientRouteModuleForHMR___, null),'), lines.push(` React.createElement(${exportName}WithoutClientChunk, props),`), lines.push(' );'), lines.push('}');
|
|
14435
14456
|
continue;
|
|
14436
14457
|
}
|
|
14437
14458
|
lines.push(createReexport(exportName, plan.serverTarget));
|
|
@@ -14689,9 +14710,14 @@ export {
|
|
|
14689
14710
|
'allowed-action-origins',
|
|
14690
14711
|
'client-version',
|
|
14691
14712
|
'react-router-serve-config',
|
|
14713
|
+
'manifest-prefix',
|
|
14692
14714
|
"bootstrap-scripts",
|
|
14693
14715
|
'server-manifest'
|
|
14694
|
-
], createReactRouterRscResolveAliases = (rootPath)=>({
|
|
14716
|
+
], createReactRouterRscResolveAliases = (rootPath, options = {})=>({
|
|
14717
|
+
...options.entrySsrPath ? {
|
|
14718
|
+
'virtual:react-router/unstable_rsc/entry-ssr': options.entrySsrPath,
|
|
14719
|
+
'virtual/react-router/unstable_rsc/entry-ssr': options.entrySsrPath
|
|
14720
|
+
} : {},
|
|
14695
14721
|
...Object.fromEntries(RSC_VIRTUAL_ALIAS_IDS.flatMap((id)=>{
|
|
14696
14722
|
let moduleId = `virtual/react-router/unstable_rsc/${id}`, modulePath = (0, external_pathe_namespaceObject.resolve)(rootPath, getVirtualModuleFilePath(moduleId));
|
|
14697
14723
|
return [
|
|
@@ -14706,8 +14732,8 @@ export {
|
|
|
14706
14732
|
];
|
|
14707
14733
|
})),
|
|
14708
14734
|
'react-router/internal/react-server-client': (0, external_pathe_namespaceObject.resolve)(rootPath, getVirtualModuleFilePath('virtual/react-router/rsc-internal-client'))
|
|
14709
|
-
}), createReactRouterRscVirtualModules = ({ allowedActionOrigins, appDirectory, basename, buildDirectory, isBuild,
|
|
14710
|
-
let rscAssetsBuildDirectory = (0, external_pathe_namespaceObject.relative)((0, external_pathe_namespaceObject.resolve)(buildDirectory, 'server'), outputClientPath),
|
|
14735
|
+
}), createReactRouterRscVirtualModules = ({ allowedActionOrigins, appDirectory, basename, buildDirectory, isBuild, outputClientPath, publicPath, routeDiscovery, routes, ssr })=>{
|
|
14736
|
+
let rscAssetsBuildDirectory = (0, external_pathe_namespaceObject.relative)((0, external_pathe_namespaceObject.resolve)(buildDirectory, 'server'), outputClientPath), serverPublicPath = normalizeAssetPrefix(publicPath);
|
|
14711
14737
|
return {
|
|
14712
14738
|
'virtual/react-router/unstable_rsc/routes': createRscRouteConfig({
|
|
14713
14739
|
appDirectory,
|
|
@@ -14729,9 +14755,33 @@ export {
|
|
|
14729
14755
|
assetsBuildDirectory: rscAssetsBuildDirectory,
|
|
14730
14756
|
publicPath
|
|
14731
14757
|
}),
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
14758
|
+
'virtual/react-router/unstable_rsc/manifest-prefix': `const manifest = __webpack_require__.rscM;
|
|
14759
|
+
const serverPrefix = ${JSON.stringify(serverPublicPath)};
|
|
14760
|
+
const appliedPrefix = manifest?.moduleLoading?.prefix;
|
|
14761
|
+
if (appliedPrefix && appliedPrefix !== serverPrefix) {
|
|
14762
|
+
const rewrite = url =>
|
|
14763
|
+
typeof url === "string" && url.startsWith(appliedPrefix)
|
|
14764
|
+
? serverPrefix + url.slice(appliedPrefix.length)
|
|
14765
|
+
: url;
|
|
14766
|
+
const rewriteAll = list => {
|
|
14767
|
+
if (Array.isArray(list)) for (let i = 0; i < list.length; i++) list[i] = rewrite(list[i]);
|
|
14768
|
+
};
|
|
14769
|
+
manifest.moduleLoading.prefix = serverPrefix;
|
|
14770
|
+
rewriteAll(manifest.entryJsFiles);
|
|
14771
|
+
for (const files of Object.values(manifest.entryCssFiles ?? {})) rewriteAll(files);
|
|
14772
|
+
for (const reference of Object.values(manifest.clientManifest ?? {})) rewriteAll(reference.cssFiles);
|
|
14773
|
+
}
|
|
14774
|
+
export const rscManifest = manifest;
|
|
14775
|
+
`,
|
|
14776
|
+
"virtual/react-router/unstable_rsc/bootstrap-scripts": `import { rscManifest } from "virtual/react-router/unstable_rsc/manifest-prefix";
|
|
14777
|
+
const entryJsFiles = rscManifest?.entryJsFiles;
|
|
14778
|
+
if (!entryJsFiles?.length) {
|
|
14779
|
+
throw new Error(
|
|
14780
|
+
"[rsbuild-plugin-react-router] The rspack RSC manifest lists no browser entry script (entryJsFiles is empty), so the server cannot render bootstrap scripts. Rspack only records entry files whose name ends in \\".js\\"; web output.filename.js values with a query (for example \\"[name].js?v=[contenthash:8]\\") or another extension are not supported in RSC mode."
|
|
14781
|
+
);
|
|
14782
|
+
}
|
|
14783
|
+
export default entryJsFiles;
|
|
14784
|
+
`,
|
|
14735
14785
|
'virtual/react-router/unstable_rsc/server-manifest': `export default function getServerManifest() {
|
|
14736
14786
|
return __webpack_require__.rscM?.serverManifest;
|
|
14737
14787
|
}
|
|
@@ -15559,7 +15609,7 @@ export {
|
|
|
15559
15609
|
'react-router/dom$': reactRouterDomPath
|
|
15560
15610
|
} : {}
|
|
15561
15611
|
};
|
|
15562
|
-
}, createRscModePlan = async ({ allowedActionOriginsForBuild, api, appDirectory, basename, buildDirectory, customServer, finalEntryRscClientPath, finalEntryRscPath, isBuild, outputClientPath, pluginName, prerenderConfig, routeConfig, routeDiscovery, routes, rootRouteFile, serverBuildFile, splitRouteModules, ssr })=>{
|
|
15612
|
+
}, createRscModePlan = async ({ allowedActionOriginsForBuild, api, appDirectory, basename, buildDirectory, customServer, finalEntryRscClientPath, finalEntryRscPath, finalEntryRscSsrPath, isBuild, outputClientPath, pluginName, prerenderConfig, routeConfig, routeDiscovery, routes, rootRouteFile, serverBuildFile, splitRouteModules, ssr })=>{
|
|
15563
15613
|
let rscServerEntryName = (serverBuildFile || 'index.js').replace(/\.js$/, '');
|
|
15564
15614
|
return {
|
|
15565
15615
|
kind: 'rsc',
|
|
@@ -15587,13 +15637,12 @@ export {
|
|
|
15587
15637
|
layer: RSC_LAYERS.rsc
|
|
15588
15638
|
}
|
|
15589
15639
|
},
|
|
15590
|
-
createVirtualModules: (publicPath
|
|
15640
|
+
createVirtualModules: (publicPath)=>createReactRouterRscVirtualModules({
|
|
15591
15641
|
allowedActionOrigins: allowedActionOriginsForBuild,
|
|
15592
15642
|
appDirectory,
|
|
15593
15643
|
basename,
|
|
15594
15644
|
buildDirectory,
|
|
15595
15645
|
isBuild,
|
|
15596
|
-
jsDistPath,
|
|
15597
15646
|
outputClientPath,
|
|
15598
15647
|
publicPath,
|
|
15599
15648
|
routeDiscovery,
|
|
@@ -15605,7 +15654,9 @@ export {
|
|
|
15605
15654
|
(0, external_pathe_namespaceObject.resolve)(rootPath, 'node_modules'),
|
|
15606
15655
|
'node_modules'
|
|
15607
15656
|
],
|
|
15608
|
-
alias: createReactRouterRscResolveAliases(rootPath
|
|
15657
|
+
alias: createReactRouterRscResolveAliases(rootPath, {
|
|
15658
|
+
entrySsrPath: finalEntryRscSsrPath
|
|
15659
|
+
})
|
|
15609
15660
|
}),
|
|
15610
15661
|
server: customServer ? void 0 : {
|
|
15611
15662
|
setup: createReactRouterRscDevServerSetup({
|
|
@@ -15685,7 +15736,7 @@ export {
|
|
|
15685
15736
|
defaultEntryName,
|
|
15686
15737
|
serverBundleEntries: artifacts.serverBundleEntries
|
|
15687
15738
|
}),
|
|
15688
|
-
createVirtualModules: (publicPath
|
|
15739
|
+
createVirtualModules: (publicPath)=>createClassicVirtualModules({
|
|
15689
15740
|
allowedActionOrigins: allowedActionOriginsForBuild,
|
|
15690
15741
|
appDirectory,
|
|
15691
15742
|
assetsBuildDirectory,
|
|
@@ -15720,10 +15771,7 @@ export {
|
|
|
15720
15771
|
library: {
|
|
15721
15772
|
type: 'module'
|
|
15722
15773
|
},
|
|
15723
|
-
module: !0
|
|
15724
|
-
...isBuild ? {
|
|
15725
|
-
chunkFilename: 'static/js/async/[id]-[contenthash:16].js'
|
|
15726
|
-
} : {}
|
|
15774
|
+
module: !0
|
|
15727
15775
|
},
|
|
15728
15776
|
webOptimization: {
|
|
15729
15777
|
avoidEntryIife: !0,
|
|
@@ -15805,11 +15853,14 @@ export {
|
|
|
15805
15853
|
}), api.onBeforeBuild(()=>{
|
|
15806
15854
|
warnOnClientSourceMaps(api.getNormalizedConfig(), (msg)=>api.logger.warn(msg), 'web');
|
|
15807
15855
|
}), api.onBeforeCreateCompiler(()=>{
|
|
15808
|
-
let
|
|
15856
|
+
let root = api.getNormalizedConfig(), web = root.environments.web;
|
|
15809
15857
|
assetPrefix = resolveEffectiveAssetPrefix({
|
|
15810
|
-
dev:
|
|
15811
|
-
output:
|
|
15858
|
+
dev: web?.dev,
|
|
15859
|
+
output: web?.output,
|
|
15812
15860
|
isBuild: 'build' === api.context.action
|
|
15861
|
+
}, {
|
|
15862
|
+
dev: root.dev,
|
|
15863
|
+
output: root.output
|
|
15813
15864
|
});
|
|
15814
15865
|
});
|
|
15815
15866
|
let configPath = findEntryFile((0, external_pathe_namespaceObject.resolve)('react-router.config')), configExists = (0, external_node_fs_namespaceObject.existsSync)(configPath), configWatchPaths = configExists ? configPath : JS_EXTENSIONS.map((extension)=>(0, external_pathe_namespaceObject.resolve)(`react-router.config${extension}`)), reactRouterUserConfig = {};
|
|
@@ -15964,6 +16015,7 @@ export {
|
|
|
15964
16015
|
buildDirectory,
|
|
15965
16016
|
finalEntryRscClientPath,
|
|
15966
16017
|
finalEntryRscPath,
|
|
16018
|
+
finalEntryRscSsrPath,
|
|
15967
16019
|
outputClientPath,
|
|
15968
16020
|
pluginName: PLUGIN_NAME,
|
|
15969
16021
|
serverBuildFile
|
|
@@ -16076,13 +16128,16 @@ export {
|
|
|
16076
16128
|
prerenderPaths: modePlan.prerenderPaths,
|
|
16077
16129
|
basename
|
|
16078
16130
|
})))), api.modifyRsbuildConfig(async (config, { mergeRsbuildConfig })=>{
|
|
16079
|
-
let
|
|
16080
|
-
|
|
16081
|
-
|
|
16131
|
+
let publicPath, webConfig = config.environments?.web, webJsFilename = webConfig?.output?.filename?.js ?? config.output?.filename?.js;
|
|
16132
|
+
if (isRscMode && 'string' == typeof webJsFilename && !/\.js$/.test(webJsFilename)) throw Error(`[${PLUGIN_NAME}] RSC mode requires web \`output.filename.js\` to end in ".js" (got ${JSON.stringify(webJsFilename)}): rspack's RSC manifest omits entry files with a query or another extension, so the server could not render bootstrap scripts.`);
|
|
16133
|
+
let vmodPlugin = (publicPath = resolveEffectiveAssetPrefix({
|
|
16134
|
+
dev: webConfig?.dev,
|
|
16135
|
+
output: webConfig?.output,
|
|
16082
16136
|
isBuild
|
|
16083
|
-
}
|
|
16084
|
-
|
|
16085
|
-
|
|
16137
|
+
}, {
|
|
16138
|
+
dev: config.dev,
|
|
16139
|
+
output: config.output
|
|
16140
|
+
}), new core_namespaceObject.rspack.experiments.VirtualModulesPlugin(mapVirtualModules(modePlan.createVirtualModules(publicPath)))), guardedLazyCompilation = guardReactRouterLazyCompilation({
|
|
16086
16141
|
lazyCompilation: Object.prototype.hasOwnProperty.call(options, 'lazyCompilation') ? pluginOptions.lazyCompilation : config.dev?.lazyCompilation ?? pluginOptions.lazyCompilation,
|
|
16087
16142
|
entryClientPath: isRscMode ? finalEntryRscClientPath : finalEntryClientPath,
|
|
16088
16143
|
prewarmReactRouterModules: !!pluginOptions.unstableLazyCompilationPrewarm
|
|
@@ -16136,9 +16191,6 @@ export {
|
|
|
16136
16191
|
}
|
|
16137
16192
|
},
|
|
16138
16193
|
output: {
|
|
16139
|
-
filename: {
|
|
16140
|
-
js: '[name].js'
|
|
16141
|
-
},
|
|
16142
16194
|
distPath: {
|
|
16143
16195
|
root: outputClientPath
|
|
16144
16196
|
}
|
|
@@ -16157,13 +16209,6 @@ export {
|
|
|
16157
16209
|
]
|
|
16158
16210
|
},
|
|
16159
16211
|
externalsType: modePlan.webExternalsType,
|
|
16160
|
-
output: {
|
|
16161
|
-
...modePlan.webOutput,
|
|
16162
|
-
publicPath: assetPrefix,
|
|
16163
|
-
...options.federation ? {
|
|
16164
|
-
chunkLoading: 'import'
|
|
16165
|
-
} : {}
|
|
16166
|
-
},
|
|
16167
16212
|
optimization: modePlan.webOptimization
|
|
16168
16213
|
}
|
|
16169
16214
|
}
|
|
@@ -16201,17 +16246,7 @@ export {
|
|
|
16201
16246
|
},
|
|
16202
16247
|
externals: modePlan.nodeExternals,
|
|
16203
16248
|
...modePlan.nodeDependencies,
|
|
16204
|
-
externalsType: resolvedServerOutput
|
|
16205
|
-
output: {
|
|
16206
|
-
chunkFormat: resolvedServerOutput,
|
|
16207
|
-
chunkLoading: nodeChunkLoading,
|
|
16208
|
-
devtoolModuleFilenameTemplate: '[absolute-resource-path]',
|
|
16209
|
-
devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]',
|
|
16210
|
-
workerChunkLoading: nodeChunkLoading,
|
|
16211
|
-
wasmLoading: 'fetch',
|
|
16212
|
-
module: 'module' === resolvedServerOutput,
|
|
16213
|
-
chunkFilename: 'static/js/async/[name].js'
|
|
16214
|
-
}
|
|
16249
|
+
externalsType: resolvedServerOutput
|
|
16215
16250
|
}
|
|
16216
16251
|
}
|
|
16217
16252
|
}
|
|
@@ -16220,7 +16255,8 @@ export {
|
|
|
16220
16255
|
}), registerReactRouterEnvironmentOutput({
|
|
16221
16256
|
api,
|
|
16222
16257
|
federation: pluginOptions.federation,
|
|
16223
|
-
resolvedServerOutput
|
|
16258
|
+
resolvedServerOutput,
|
|
16259
|
+
webOutput: modePlan.webOutput
|
|
16224
16260
|
}), 'classic' === modePlan.kind && useRouteModuleTransformLoader && api.modifyEnvironmentConfig(async (config, { name, mergeEnvironmentConfig })=>'web' !== name && 'node' !== name ? config : mergeEnvironmentConfig(config, {
|
|
16225
16261
|
tools: {
|
|
16226
16262
|
rspack: (rspackConfig)=>{
|