@c0va23/react-router-dev 7.10.1 → 7.13.1
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/CHANGELOG.md +84 -8
- package/dist/cli/index.js +72 -59
- package/dist/config/default-rsc-entries/entry.rsc.tsx +33 -11
- package/dist/config/default-rsc-entries/entry.ssr.tsx +22 -15
- package/dist/config.d.ts +51 -0
- package/dist/config.js +1 -1
- package/dist/routes.js +1 -1
- package/dist/vite/cloudflare.js +11 -9
- package/dist/vite.js +892 -280
- package/package.json +21 -10
- package/rsc-types.d.ts +21 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,89 @@
|
|
|
1
1
|
# `@react-router/dev`
|
|
2
2
|
|
|
3
|
+
## 7.13.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies:
|
|
8
|
+
- `react-router@7.13.1`
|
|
9
|
+
- `@react-router/node@7.13.1`
|
|
10
|
+
- `@react-router/serve@7.13.1`
|
|
11
|
+
|
|
12
|
+
## 7.13.0
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Bump @remix-run/node-fetch-server dep ([#14704](https://github.com/remix-run/react-router/pull/14704))
|
|
17
|
+
- Updated dependencies:
|
|
18
|
+
- `react-router@7.13.0`
|
|
19
|
+
- `@react-router/node@7.13.0`
|
|
20
|
+
- `@react-router/serve@7.13.0`
|
|
21
|
+
|
|
22
|
+
## 7.12.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- Add additional layer of CSRF protection by rejecting submissions to UI routes from external origins. If you need to permit access to specific external origins, you can specify them in the `react-router.config.ts` config `allowedActionOrigins` field. ([#14708](https://github.com/remix-run/react-router/pull/14708))
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Fix `Maximum call stack size exceeded` errors when HMR is triggered against code with cyclic imports ([#14522](https://github.com/remix-run/react-router/pull/14522))
|
|
31
|
+
|
|
32
|
+
- fix(vite): Skip SSR middleware in preview server for SPA mode ([#14673](https://github.com/remix-run/react-router/pull/14673))
|
|
33
|
+
|
|
34
|
+
- \[UNSTABLE] Add a new `future.unstable_trailingSlashAwareDataRequests` flag to provide consistent behavior of `request.pathname` inside `middleware`, `loader`, and `action` functions on document and data requests when a trailing slash is present in the browser URL. ([#14644](https://github.com/remix-run/react-router/pull/14644))
|
|
35
|
+
|
|
36
|
+
Currently, your HTTP and `request` pathnames would be as follows for `/a/b/c` and `/a/b/c/`
|
|
37
|
+
|
|
38
|
+
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname\`** |
|
|
39
|
+
| ------------ | ----------------- | ------------------------ |
|
|
40
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
41
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
42
|
+
|
|
43
|
+
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname\`** |
|
|
44
|
+
| ------------- | ----------------- | ------------------------ |
|
|
45
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
46
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ⚠️ |
|
|
47
|
+
|
|
48
|
+
With this flag enabled, these pathnames will be made consistent though a new `_.data` format for client-side `.data` requests:
|
|
49
|
+
|
|
50
|
+
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname\`** |
|
|
51
|
+
| ------------ | ----------------- | ------------------------ |
|
|
52
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
53
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
54
|
+
|
|
55
|
+
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname\`** |
|
|
56
|
+
| ------------- | ------------------ | ------------------------ |
|
|
57
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
58
|
+
| **Data** | `/a/b/c/_.data` ⬅️ | `/a/b/c/` ✅ |
|
|
59
|
+
|
|
60
|
+
This a bug fix but we are putting it behind an opt-in flag because it has the potential to be a "breaking bug fix" if you are relying on the URL format for any other application or caching logic.
|
|
61
|
+
|
|
62
|
+
Enabling this flag also changes the format of client side `.data` requests from `/_root.data` to `/_.data` when navigating to `/` to align with the new format. This does not impact the `request` pathname which is still `/` in all cases.
|
|
63
|
+
|
|
64
|
+
- Updated dependencies:
|
|
65
|
+
- `react-router@7.12.0`
|
|
66
|
+
- `@react-router/node@7.12.0`
|
|
67
|
+
- `@react-router/serve@7.12.0`
|
|
68
|
+
|
|
69
|
+
## 7.11.0
|
|
70
|
+
|
|
71
|
+
### Minor Changes
|
|
72
|
+
|
|
73
|
+
- feat: add `vite preview` support ([#14507](https://github.com/remix-run/react-router/pull/14507))
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- rsc framework mode manual chunking for react and react-router deps ([#14655](https://github.com/remix-run/react-router/pull/14655))
|
|
78
|
+
- add support for throwing redirect Response's at RSC render time ([#14596](https://github.com/remix-run/react-router/pull/14596))
|
|
79
|
+
- support custom entrypoints for RSC framework mode ([#14643](https://github.com/remix-run/react-router/pull/14643))
|
|
80
|
+
- `routeRSCServerRequest` replace `fetchServer` with `serverResponse` ([#14597](https://github.com/remix-run/react-router/pull/14597))
|
|
81
|
+
- rsc framewlrk mode - optimize react-server-dom-webpack if in project package.json ([#14656](https://github.com/remix-run/react-router/pull/14656))
|
|
82
|
+
- Updated dependencies:
|
|
83
|
+
- `react-router@7.11.0`
|
|
84
|
+
- `@react-router/serve@7.11.0`
|
|
85
|
+
- `@react-router/node@7.11.0`
|
|
86
|
+
|
|
3
87
|
## 7.10.1
|
|
4
88
|
|
|
5
89
|
### Patch Changes
|
|
@@ -229,7 +313,6 @@
|
|
|
229
313
|
- Stabilize middleware and context APIs. ([#14215](https://github.com/remix-run/react-router/pull/14215))
|
|
230
314
|
|
|
231
315
|
We have removed the `unstable_` prefix from the following APIs and they are now considered stable and ready for production use:
|
|
232
|
-
|
|
233
316
|
- [`RouterContextProvider`](https://reactrouter.com/api/utils/RouterContextProvider)
|
|
234
317
|
- [`createContext`](https://reactrouter.com/api/utils/createContext)
|
|
235
318
|
- `createBrowserRouter` [`getContext`](https://reactrouter.com/api/data-routers/createBrowserRouter#optsgetcontext) option
|
|
@@ -972,7 +1055,6 @@
|
|
|
972
1055
|
```
|
|
973
1056
|
|
|
974
1057
|
This initial implementation targets type inference for:
|
|
975
|
-
|
|
976
1058
|
- `Params` : Path parameters from your routing config in `routes.ts` including file-based routing
|
|
977
1059
|
- `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module
|
|
978
1060
|
- `ActionData` : Action data from `action` and/or `clientAction` within your route module
|
|
@@ -987,7 +1069,6 @@
|
|
|
987
1069
|
```
|
|
988
1070
|
|
|
989
1071
|
Check out our docs for more:
|
|
990
|
-
|
|
991
1072
|
- [_Explanations > Type Safety_](https://reactrouter.com/dev/guides/explanation/type-safety)
|
|
992
1073
|
- [_How-To > Setting up type safety_](https://reactrouter.com/dev/guides/how-to/setting-up-type-safety)
|
|
993
1074
|
|
|
@@ -1187,7 +1268,6 @@
|
|
|
1187
1268
|
- Vite: Provide `Unstable_ServerBundlesFunction` and `Unstable_VitePluginConfig` types ([#8654](https://github.com/remix-run/remix/pull/8654))
|
|
1188
1269
|
|
|
1189
1270
|
- Vite: add `--sourcemapClient` and `--sourcemapServer` flags to `remix vite:build` ([#8613](https://github.com/remix-run/remix/pull/8613))
|
|
1190
|
-
|
|
1191
1271
|
- `--sourcemapClient`
|
|
1192
1272
|
|
|
1193
1273
|
- `--sourcemapClient=inline`
|
|
@@ -1524,7 +1604,6 @@
|
|
|
1524
1604
|
- Add support for `clientLoader`/`clientAction`/`HydrateFallback` route exports ([RFC](https://github.com/remix-run/remix/discussions/7634)) ([#8173](https://github.com/remix-run/remix/pull/8173))
|
|
1525
1605
|
|
|
1526
1606
|
Remix now supports loaders/actions that run on the client (in addition to, or instead of the loader/action that runs on the server). While we still recommend server loaders/actions for the majority of your data needs in a Remix app - these provide some levers you can pull for more advanced use-cases such as:
|
|
1527
|
-
|
|
1528
1607
|
- Leveraging a data source local to the browser (i.e., `localStorage`)
|
|
1529
1608
|
- Managing a client-side cache of server data (like `IndexedDB`)
|
|
1530
1609
|
- Bypassing the Remix server in a BFF setup and hitting your API directly from the browser
|
|
@@ -1928,7 +2007,6 @@
|
|
|
1928
2007
|
- Output esbuild metafiles for bundle analysis ([#6772](https://github.com/remix-run/remix/pull/6772))
|
|
1929
2008
|
|
|
1930
2009
|
Written to server build directory (`build/` by default):
|
|
1931
|
-
|
|
1932
2010
|
- `metafile.css.json`
|
|
1933
2011
|
- `metafile.js.json` (browser JS)
|
|
1934
2012
|
- `metafile.server.json` (server JS)
|
|
@@ -2026,7 +2104,6 @@
|
|
|
2026
2104
|
- built-in tls support ([#6483](https://github.com/remix-run/remix/pull/6483))
|
|
2027
2105
|
|
|
2028
2106
|
New options:
|
|
2029
|
-
|
|
2030
2107
|
- `--tls-key` / `tlsKey`: TLS key
|
|
2031
2108
|
- `--tls-cert` / `tlsCert`: TLS Certificate
|
|
2032
2109
|
|
|
@@ -2297,7 +2374,6 @@
|
|
|
2297
2374
|
```
|
|
2298
2375
|
|
|
2299
2376
|
The dev server will:
|
|
2300
|
-
|
|
2301
2377
|
- force `NODE_ENV=development` and warn you if it was previously set to something else
|
|
2302
2378
|
- rebuild your app whenever your Remix app code changes
|
|
2303
2379
|
- restart your app server whenever rebuilds succeed
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @react-router/dev v7.
|
|
3
|
+
* @react-router/dev v7.13.1
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) Remix Software Inc.
|
|
6
6
|
*
|
|
@@ -217,7 +217,7 @@ function validateRouteConfig({
|
|
|
217
217
|
`Route config in "${routeConfigFile}" is invalid.`,
|
|
218
218
|
root ? `${root}` : [],
|
|
219
219
|
nested ? Object.entries(nested).map(
|
|
220
|
-
([
|
|
220
|
+
([path10, message]) => `Path: routes.${path10}
|
|
221
221
|
${message}`
|
|
222
222
|
) : []
|
|
223
223
|
].flat().join("\n\n")
|
|
@@ -376,7 +376,7 @@ async function resolveConfig({
|
|
|
376
376
|
basename: basename3,
|
|
377
377
|
buildDirectory: userBuildDirectory,
|
|
378
378
|
buildEnd,
|
|
379
|
-
prerender,
|
|
379
|
+
prerender: prerender2,
|
|
380
380
|
routeDiscovery: userRouteDiscovery,
|
|
381
381
|
serverBuildFile,
|
|
382
382
|
serverBundles,
|
|
@@ -390,15 +390,15 @@ async function resolveConfig({
|
|
|
390
390
|
if (!ssr && serverBundles) {
|
|
391
391
|
serverBundles = void 0;
|
|
392
392
|
}
|
|
393
|
-
if (
|
|
393
|
+
if (prerender2) {
|
|
394
394
|
let isValidPrerenderPathsConfig = (p) => typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
|
|
395
|
-
let isValidPrerenderConfig = isValidPrerenderPathsConfig(
|
|
395
|
+
let isValidPrerenderConfig = isValidPrerenderPathsConfig(prerender2) || typeof prerender2 === "object" && "paths" in prerender2 && isValidPrerenderPathsConfig(prerender2.paths);
|
|
396
396
|
if (!isValidPrerenderConfig) {
|
|
397
397
|
return err(
|
|
398
398
|
"The `prerender`/`prerender.paths` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths."
|
|
399
399
|
);
|
|
400
400
|
}
|
|
401
|
-
let isValidConcurrencyConfig = typeof
|
|
401
|
+
let isValidConcurrencyConfig = typeof prerender2 != "object" || !("unstable_concurrency" in prerender2) || typeof prerender2.unstable_concurrency === "number" && Number.isInteger(prerender2.unstable_concurrency) && prerender2.unstable_concurrency > 0;
|
|
402
402
|
if (!isValidConcurrencyConfig) {
|
|
403
403
|
return err(
|
|
404
404
|
"The `prerender.unstable_concurrency` config must be a positive integer if specified."
|
|
@@ -506,23 +506,27 @@ async function resolveConfig({
|
|
|
506
506
|
let future = {
|
|
507
507
|
unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,
|
|
508
508
|
unstable_subResourceIntegrity: userAndPresetConfigs.future?.unstable_subResourceIntegrity ?? false,
|
|
509
|
+
unstable_trailingSlashAwareDataRequests: userAndPresetConfigs.future?.unstable_trailingSlashAwareDataRequests ?? false,
|
|
510
|
+
unstable_previewServerPrerendering: userAndPresetConfigs.future?.unstable_previewServerPrerendering ?? false,
|
|
509
511
|
v8_middleware: userAndPresetConfigs.future?.v8_middleware ?? false,
|
|
510
512
|
v8_splitRouteModules: userAndPresetConfigs.future?.v8_splitRouteModules ?? false,
|
|
511
513
|
v8_viteEnvironmentApi: userAndPresetConfigs.future?.v8_viteEnvironmentApi ?? false
|
|
512
514
|
};
|
|
515
|
+
let allowedActionOrigins = userAndPresetConfigs.allowedActionOrigins ?? false;
|
|
513
516
|
let reactRouterConfig = deepFreeze({
|
|
514
517
|
appDirectory,
|
|
515
518
|
basename: basename3,
|
|
516
519
|
buildDirectory,
|
|
517
520
|
buildEnd,
|
|
518
521
|
future,
|
|
519
|
-
prerender,
|
|
522
|
+
prerender: prerender2,
|
|
520
523
|
routes: routes2,
|
|
521
524
|
routeDiscovery,
|
|
522
525
|
serverBuildFile,
|
|
523
526
|
serverBundles,
|
|
524
527
|
serverModuleFormat,
|
|
525
528
|
ssr,
|
|
529
|
+
allowedActionOrigins,
|
|
526
530
|
unstable_routeConfig: routeConfig
|
|
527
531
|
});
|
|
528
532
|
for (let preset of reactRouterUserConfig.presets ?? []) {
|
|
@@ -582,11 +586,11 @@ async function createConfigLoader({
|
|
|
582
586
|
if (!fsWatcher) {
|
|
583
587
|
fsWatcher = import_chokidar.default.watch([root, appDirectory], {
|
|
584
588
|
ignoreInitial: true,
|
|
585
|
-
ignored: (
|
|
586
|
-
let dirname5 = import_pathe3.default.dirname(
|
|
589
|
+
ignored: (path10) => {
|
|
590
|
+
let dirname5 = import_pathe3.default.dirname(path10);
|
|
587
591
|
return !dirname5.startsWith(appDirectory) && // Ensure we're only watching files outside of the app directory
|
|
588
592
|
// that are at the root level, not nested in subdirectories
|
|
589
|
-
|
|
593
|
+
path10 !== root && // Watch the root directory itself
|
|
590
594
|
dirname5 !== root;
|
|
591
595
|
}
|
|
592
596
|
});
|
|
@@ -911,7 +915,7 @@ function fullpath(lineage2) {
|
|
|
911
915
|
if (lineage2.length === 1 && route?.id === "root") return "/";
|
|
912
916
|
const isLayout = route && route.index !== true && route.path === void 0;
|
|
913
917
|
if (isLayout) return void 0;
|
|
914
|
-
return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((
|
|
918
|
+
return "/" + lineage2.map((route2) => route2.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path10) => path10 !== void 0 && path10 !== "").join("/");
|
|
915
919
|
}
|
|
916
920
|
var init_route = __esm({
|
|
917
921
|
"typegen/route.ts"() {
|
|
@@ -956,6 +960,7 @@ function generateServerBuild(ctx) {
|
|
|
956
960
|
export const routeDiscovery: ServerBuild["routeDiscovery"];
|
|
957
961
|
export const routes: ServerBuild["routes"];
|
|
958
962
|
export const ssr: ServerBuild["ssr"];
|
|
963
|
+
export const allowedActionOrigins: ServerBuild["allowedActionOrigins"];
|
|
959
964
|
export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
|
|
960
965
|
}
|
|
961
966
|
`;
|
|
@@ -1094,8 +1099,8 @@ function routeModulesType(ctx) {
|
|
|
1094
1099
|
);
|
|
1095
1100
|
}
|
|
1096
1101
|
function isInAppDirectory(ctx, routeFile) {
|
|
1097
|
-
const
|
|
1098
|
-
return
|
|
1102
|
+
const path10 = Path3.resolve(ctx.config.appDirectory, routeFile);
|
|
1103
|
+
return path10.startsWith(ctx.config.appDirectory);
|
|
1099
1104
|
}
|
|
1100
1105
|
function getRouteAnnotations({
|
|
1101
1106
|
ctx,
|
|
@@ -1207,21 +1212,21 @@ function getRouteAnnotations({
|
|
|
1207
1212
|
return { filename: filename2, content };
|
|
1208
1213
|
}
|
|
1209
1214
|
function relativeImportSource(from, to) {
|
|
1210
|
-
let
|
|
1211
|
-
let extension = Path3.extname(
|
|
1212
|
-
|
|
1213
|
-
if (!
|
|
1215
|
+
let path10 = Path3.relative(Path3.dirname(from), to);
|
|
1216
|
+
let extension = Path3.extname(path10);
|
|
1217
|
+
path10 = Path3.join(Path3.dirname(path10), Pathe.filename(path10));
|
|
1218
|
+
if (!path10.startsWith("../")) path10 = "./" + path10;
|
|
1214
1219
|
if (!extension || /\.(js|ts)x?$/.test(extension)) {
|
|
1215
1220
|
extension = ".js";
|
|
1216
1221
|
}
|
|
1217
|
-
return
|
|
1222
|
+
return path10 + extension;
|
|
1218
1223
|
}
|
|
1219
1224
|
function rootDirsPath(ctx, typesPath) {
|
|
1220
1225
|
const rel = Path3.relative(typesDirectory(ctx), typesPath);
|
|
1221
1226
|
return Path3.join(ctx.rootDirectory, rel);
|
|
1222
1227
|
}
|
|
1223
|
-
function paramsType(
|
|
1224
|
-
const params = parse2(
|
|
1228
|
+
function paramsType(path10) {
|
|
1229
|
+
const params = parse2(path10);
|
|
1225
1230
|
return t2.tsTypeLiteral(
|
|
1226
1231
|
Object.entries(params).map(([param, isRequired]) => {
|
|
1227
1232
|
const property = t2.tsPropertySignature(
|
|
@@ -1373,11 +1378,9 @@ var init_has_rsc_plugin = __esm({
|
|
|
1373
1378
|
});
|
|
1374
1379
|
|
|
1375
1380
|
// vite/node-adapter.ts
|
|
1376
|
-
var import_node_fetch_server;
|
|
1377
1381
|
var init_node_adapter = __esm({
|
|
1378
1382
|
"vite/node-adapter.ts"() {
|
|
1379
1383
|
"use strict";
|
|
1380
|
-
import_node_fetch_server = require("@remix-run/node-fetch-server");
|
|
1381
1384
|
init_invariant();
|
|
1382
1385
|
}
|
|
1383
1386
|
});
|
|
@@ -1553,6 +1556,16 @@ var init_warn_on_client_source_maps = __esm({
|
|
|
1553
1556
|
}
|
|
1554
1557
|
});
|
|
1555
1558
|
|
|
1559
|
+
// vite/plugins/prerender.ts
|
|
1560
|
+
var import_promises2, import_node_path2;
|
|
1561
|
+
var init_prerender = __esm({
|
|
1562
|
+
"vite/plugins/prerender.ts"() {
|
|
1563
|
+
"use strict";
|
|
1564
|
+
import_promises2 = require("fs/promises");
|
|
1565
|
+
import_node_path2 = __toESM(require("path"));
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
|
|
1556
1569
|
// vite/plugin.ts
|
|
1557
1570
|
async function resolveViteConfig({
|
|
1558
1571
|
configFile,
|
|
@@ -1595,11 +1608,11 @@ function getServerBundleIds(ctx) {
|
|
|
1595
1608
|
async function cleanBuildDirectory(viteConfig, ctx) {
|
|
1596
1609
|
let buildDirectory = ctx.reactRouterConfig.buildDirectory;
|
|
1597
1610
|
let isWithinRoot = () => {
|
|
1598
|
-
let relativePath =
|
|
1599
|
-
return !relativePath.startsWith("..") && !
|
|
1611
|
+
let relativePath = path8.relative(ctx.rootDirectory, buildDirectory);
|
|
1612
|
+
return !relativePath.startsWith("..") && !path8.isAbsolute(relativePath);
|
|
1600
1613
|
};
|
|
1601
1614
|
if (viteConfig.build.emptyOutDir ?? isWithinRoot()) {
|
|
1602
|
-
await (0,
|
|
1615
|
+
await (0, import_promises3.rm)(buildDirectory, { force: true, recursive: true });
|
|
1603
1616
|
}
|
|
1604
1617
|
}
|
|
1605
1618
|
async function cleanViteManifests(environmentsOptions, ctx) {
|
|
@@ -1607,7 +1620,7 @@ async function cleanViteManifests(environmentsOptions, ctx) {
|
|
|
1607
1620
|
([environmentName, options]) => {
|
|
1608
1621
|
let outDir = options.build?.outDir;
|
|
1609
1622
|
invariant(outDir, `Expected build.outDir for ${environmentName}`);
|
|
1610
|
-
return
|
|
1623
|
+
return path8.join(outDir, ".vite/manifest.json");
|
|
1611
1624
|
}
|
|
1612
1625
|
);
|
|
1613
1626
|
await Promise.all(
|
|
@@ -1615,12 +1628,12 @@ async function cleanViteManifests(environmentsOptions, ctx) {
|
|
|
1615
1628
|
let manifestExists = (0, import_node_fs3.existsSync)(viteManifestPath);
|
|
1616
1629
|
if (!manifestExists) return;
|
|
1617
1630
|
if (!ctx.viteManifestEnabled) {
|
|
1618
|
-
await (0,
|
|
1631
|
+
await (0, import_promises3.rm)(viteManifestPath, { force: true, recursive: true });
|
|
1619
1632
|
}
|
|
1620
|
-
let viteDir =
|
|
1621
|
-
let viteDirFiles = await (0,
|
|
1633
|
+
let viteDir = path8.dirname(viteManifestPath);
|
|
1634
|
+
let viteDirFiles = await (0, import_promises3.readdir)(viteDir, { recursive: true });
|
|
1622
1635
|
if (viteDirFiles.length === 0) {
|
|
1623
|
-
await (0,
|
|
1636
|
+
await (0, import_promises3.rm)(viteDir, { force: true, recursive: true });
|
|
1624
1637
|
}
|
|
1625
1638
|
})
|
|
1626
1639
|
);
|
|
@@ -1634,10 +1647,10 @@ function mergeEnvironmentOptions(base, ...overrides) {
|
|
|
1634
1647
|
}
|
|
1635
1648
|
async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
|
|
1636
1649
|
let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
|
|
1637
|
-
let packageRoot =
|
|
1650
|
+
let packageRoot = path8.dirname(
|
|
1638
1651
|
require.resolve("@react-router/dev/package.json")
|
|
1639
1652
|
);
|
|
1640
|
-
let { moduleSyncEnabled } = await import(`file:///${
|
|
1653
|
+
let { moduleSyncEnabled } = await import(`file:///${path8.join(packageRoot, "module-sync-enabled/index.mjs")}`);
|
|
1641
1654
|
let vite2 = getVite();
|
|
1642
1655
|
function getBaseOptions({
|
|
1643
1656
|
viteUserConfig
|
|
@@ -1716,7 +1729,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
|
|
|
1716
1729
|
ctx.entryClientFilePath,
|
|
1717
1730
|
...Object.values(ctx.reactRouterConfig.routes).flatMap(
|
|
1718
1731
|
(route) => {
|
|
1719
|
-
let routeFilePath =
|
|
1732
|
+
let routeFilePath = path8.resolve(
|
|
1720
1733
|
ctx.reactRouterConfig.appDirectory,
|
|
1721
1734
|
route.file
|
|
1722
1735
|
);
|
|
@@ -1740,7 +1753,7 @@ async function getEnvironmentOptionsResolvers(ctx, viteCommand) {
|
|
|
1740
1753
|
) : null;
|
|
1741
1754
|
let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
|
|
1742
1755
|
let assetsDir = (ctx.reactRouterConfig.future.v8_viteEnvironmentApi ? viteUserConfig?.environments?.client?.build?.assetsDir : null) ?? viteUserConfig?.build?.assetsDir ?? "assets";
|
|
1743
|
-
return
|
|
1756
|
+
return path8.posix.join(
|
|
1744
1757
|
assetsDir,
|
|
1745
1758
|
`[name]${routeChunkSuffix}-[hash].js`
|
|
1746
1759
|
);
|
|
@@ -1790,17 +1803,16 @@ function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
|
|
|
1790
1803
|
function isNonNullable(x) {
|
|
1791
1804
|
return x != null;
|
|
1792
1805
|
}
|
|
1793
|
-
var import_node_crypto, import_node_fs3,
|
|
1806
|
+
var import_node_crypto, import_node_fs3, import_promises3, path8, url, babel2, import_react_router2, import_es_module_lexer, import_pick3, import_jsesc, import_picocolors5, import_kebabCase, CLIENT_NON_COMPONENT_EXPORTS, CLIENT_ROUTE_EXPORTS, BUILD_CLIENT_ROUTE_QUERY_STRING, SSR_BUNDLE_PREFIX, virtualHmrRuntime, virtualInjectHmrRuntime, virtual, getServerBuildDirectory, getClientBuildDirectory, defaultEntriesDir, defaultEntries, REACT_REFRESH_HEADER;
|
|
1794
1807
|
var init_plugin = __esm({
|
|
1795
1808
|
"vite/plugin.ts"() {
|
|
1796
1809
|
"use strict";
|
|
1797
1810
|
import_node_crypto = require("crypto");
|
|
1798
1811
|
import_node_fs3 = require("fs");
|
|
1799
|
-
|
|
1800
|
-
|
|
1812
|
+
import_promises3 = require("fs/promises");
|
|
1813
|
+
path8 = __toESM(require("path"));
|
|
1801
1814
|
url = __toESM(require("url"));
|
|
1802
1815
|
babel2 = __toESM(require("@babel/core"));
|
|
1803
|
-
import_node_fetch_server2 = require("@remix-run/node-fetch-server");
|
|
1804
1816
|
import_react_router2 = require("react-router");
|
|
1805
1817
|
import_es_module_lexer = require("es-module-lexer");
|
|
1806
1818
|
import_pick3 = __toESM(require("lodash/pick"));
|
|
@@ -1827,6 +1839,7 @@ var init_plugin = __esm({
|
|
|
1827
1839
|
init_load_dotenv();
|
|
1828
1840
|
init_validate_plugin_order();
|
|
1829
1841
|
init_warn_on_client_source_maps();
|
|
1842
|
+
init_prerender();
|
|
1830
1843
|
CLIENT_NON_COMPONENT_EXPORTS = [
|
|
1831
1844
|
"clientAction",
|
|
1832
1845
|
"clientLoader",
|
|
@@ -1852,20 +1865,20 @@ var init_plugin = __esm({
|
|
|
1852
1865
|
serverManifest: create("server-manifest"),
|
|
1853
1866
|
browserManifest: create("browser-manifest")
|
|
1854
1867
|
};
|
|
1855
|
-
getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) =>
|
|
1868
|
+
getServerBuildDirectory = (reactRouterConfig, { serverBundleId } = {}) => path8.join(
|
|
1856
1869
|
reactRouterConfig.buildDirectory,
|
|
1857
1870
|
"server",
|
|
1858
1871
|
...serverBundleId ? [serverBundleId] : []
|
|
1859
1872
|
);
|
|
1860
|
-
getClientBuildDirectory = (reactRouterConfig) =>
|
|
1861
|
-
defaultEntriesDir =
|
|
1862
|
-
|
|
1873
|
+
getClientBuildDirectory = (reactRouterConfig) => path8.join(reactRouterConfig.buildDirectory, "client");
|
|
1874
|
+
defaultEntriesDir = path8.resolve(
|
|
1875
|
+
path8.dirname(require.resolve("@react-router/dev/package.json")),
|
|
1863
1876
|
"dist",
|
|
1864
1877
|
"config",
|
|
1865
1878
|
"defaults"
|
|
1866
1879
|
);
|
|
1867
1880
|
defaultEntries = (0, import_node_fs3.readdirSync)(defaultEntriesDir).map(
|
|
1868
|
-
(filename2) =>
|
|
1881
|
+
(filename2) => path8.join(defaultEntriesDir, filename2)
|
|
1869
1882
|
);
|
|
1870
1883
|
invariant(defaultEntries.length > 0, "No default entries found");
|
|
1871
1884
|
REACT_REFRESH_HEADER = `
|
|
@@ -2150,8 +2163,8 @@ var import_picocolors9 = __toESM(require("picocolors"));
|
|
|
2150
2163
|
|
|
2151
2164
|
// cli/commands.ts
|
|
2152
2165
|
var import_node_fs4 = require("fs");
|
|
2153
|
-
var
|
|
2154
|
-
var
|
|
2166
|
+
var import_promises4 = require("fs/promises");
|
|
2167
|
+
var path9 = __toESM(require("path"));
|
|
2155
2168
|
var import_exit_hook = __toESM(require("exit-hook"));
|
|
2156
2169
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
2157
2170
|
var import_react_router3 = require("react-router");
|
|
@@ -2324,14 +2337,14 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2324
2337
|
console.error(import_picocolors8.default.red(`No default server entry detected.`));
|
|
2325
2338
|
return;
|
|
2326
2339
|
}
|
|
2327
|
-
let defaultsDirectory =
|
|
2328
|
-
|
|
2340
|
+
let defaultsDirectory = path9.resolve(
|
|
2341
|
+
path9.dirname(require.resolve("@react-router/dev/package.json")),
|
|
2329
2342
|
"dist",
|
|
2330
2343
|
"config",
|
|
2331
2344
|
"defaults"
|
|
2332
2345
|
);
|
|
2333
|
-
let defaultEntryClient =
|
|
2334
|
-
let defaultEntryServer =
|
|
2346
|
+
let defaultEntryClient = path9.resolve(defaultsDirectory, "entry.client.tsx");
|
|
2347
|
+
let defaultEntryServer = path9.resolve(
|
|
2335
2348
|
defaultsDirectory,
|
|
2336
2349
|
`entry.server.node.tsx`
|
|
2337
2350
|
);
|
|
@@ -2340,19 +2353,19 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2340
2353
|
let useTypeScript = flags.typescript ?? true;
|
|
2341
2354
|
let outputExtension = useTypeScript ? "tsx" : "jsx";
|
|
2342
2355
|
let outputEntry = `${entry}.${outputExtension}`;
|
|
2343
|
-
let outputFile =
|
|
2356
|
+
let outputFile = path9.resolve(appDirectory, outputEntry);
|
|
2344
2357
|
if (!useTypeScript) {
|
|
2345
2358
|
let javascript = await transpile(contents, {
|
|
2346
2359
|
cwd: rootDirectory,
|
|
2347
2360
|
filename: isServerEntry ? defaultEntryServer : defaultEntryClient
|
|
2348
2361
|
});
|
|
2349
|
-
await (0,
|
|
2362
|
+
await (0, import_promises4.writeFile)(outputFile, javascript, "utf-8");
|
|
2350
2363
|
} else {
|
|
2351
|
-
await (0,
|
|
2364
|
+
await (0, import_promises4.writeFile)(outputFile, contents, "utf-8");
|
|
2352
2365
|
}
|
|
2353
2366
|
console.log(
|
|
2354
2367
|
import_picocolors8.default.blue(
|
|
2355
|
-
`Entry file ${entry} created at ${
|
|
2368
|
+
`Entry file ${entry} created at ${path9.relative(
|
|
2356
2369
|
rootDirectory,
|
|
2357
2370
|
outputFile
|
|
2358
2371
|
)}.`
|
|
@@ -2361,16 +2374,16 @@ async function generateEntry(entry, rootDirectory, flags = {}) {
|
|
|
2361
2374
|
}
|
|
2362
2375
|
function resolveRootDirectory(root, flags) {
|
|
2363
2376
|
if (root) {
|
|
2364
|
-
return
|
|
2377
|
+
return path9.resolve(root);
|
|
2365
2378
|
}
|
|
2366
|
-
return process.env.REACT_ROUTER_ROOT || (flags?.config ?
|
|
2379
|
+
return process.env.REACT_ROUTER_ROOT || (flags?.config ? path9.dirname(path9.resolve(flags.config)) : process.cwd());
|
|
2367
2380
|
}
|
|
2368
2381
|
async function checkForEntry(rootDirectory, appDirectory, entries2) {
|
|
2369
2382
|
for (let entry of entries2) {
|
|
2370
|
-
let entryPath =
|
|
2383
|
+
let entryPath = path9.resolve(appDirectory, entry);
|
|
2371
2384
|
let exists = (0, import_node_fs4.existsSync)(entryPath);
|
|
2372
2385
|
if (exists) {
|
|
2373
|
-
let relative7 =
|
|
2386
|
+
let relative7 = path9.relative(rootDirectory, entryPath);
|
|
2374
2387
|
console.error(import_picocolors8.default.red(`Entry file ${relative7} already exists.`));
|
|
2375
2388
|
return process.exit(1);
|
|
2376
2389
|
}
|
|
@@ -2378,12 +2391,12 @@ async function checkForEntry(rootDirectory, appDirectory, entries2) {
|
|
|
2378
2391
|
}
|
|
2379
2392
|
async function createServerEntry(rootDirectory, appDirectory, inputFile) {
|
|
2380
2393
|
await checkForEntry(rootDirectory, appDirectory, serverEntries);
|
|
2381
|
-
let contents = await (0,
|
|
2394
|
+
let contents = await (0, import_promises4.readFile)(inputFile, "utf-8");
|
|
2382
2395
|
return contents;
|
|
2383
2396
|
}
|
|
2384
2397
|
async function createClientEntry(rootDirectory, appDirectory, inputFile) {
|
|
2385
2398
|
await checkForEntry(rootDirectory, appDirectory, clientEntries);
|
|
2386
|
-
let contents = await (0,
|
|
2399
|
+
let contents = await (0, import_promises4.readFile)(inputFile, "utf-8");
|
|
2387
2400
|
return contents;
|
|
2388
2401
|
}
|
|
2389
2402
|
async function typegen(root, flags) {
|
|
@@ -6,22 +6,36 @@ import {
|
|
|
6
6
|
loadServerAction,
|
|
7
7
|
renderToReadableStream,
|
|
8
8
|
} from "@vitejs/plugin-rsc/rsc";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
RouterContextProvider,
|
|
11
|
+
unstable_matchRSCServerRequest as matchRSCServerRequest,
|
|
12
|
+
} from "react-router";
|
|
10
13
|
|
|
14
|
+
// Import the routes generated by routes.ts
|
|
11
15
|
import routes from "virtual:react-router/unstable_rsc/routes";
|
|
12
16
|
import basename from "virtual:react-router/unstable_rsc/basename";
|
|
13
17
|
import unstable_reactRouterServeConfig from "virtual:react-router/unstable_rsc/react-router-serve-config";
|
|
14
18
|
|
|
15
|
-
export
|
|
16
|
-
|
|
19
|
+
export { unstable_reactRouterServeConfig };
|
|
20
|
+
|
|
21
|
+
export function fetchServer(
|
|
22
|
+
request: Request,
|
|
23
|
+
requestContext?: RouterContextProvider,
|
|
24
|
+
) {
|
|
25
|
+
return matchRSCServerRequest({
|
|
26
|
+
basename,
|
|
27
|
+
// Provide the React Server touchpoints.
|
|
17
28
|
createTemporaryReferenceSet,
|
|
18
29
|
decodeAction,
|
|
19
30
|
decodeFormState,
|
|
20
31
|
decodeReply,
|
|
21
32
|
loadServerAction,
|
|
33
|
+
// The incoming request.
|
|
22
34
|
request,
|
|
35
|
+
requestContext,
|
|
36
|
+
// The app routes.
|
|
23
37
|
routes,
|
|
24
|
-
|
|
38
|
+
// Encode the match with the React Server implementation.
|
|
25
39
|
generateResponse(match, options) {
|
|
26
40
|
return new Response(renderToReadableStream(match.payload, options), {
|
|
27
41
|
status: match.statusCode,
|
|
@@ -31,14 +45,22 @@ export async function fetchServer(request: Request) {
|
|
|
31
45
|
});
|
|
32
46
|
}
|
|
33
47
|
|
|
34
|
-
export {
|
|
48
|
+
export default {
|
|
49
|
+
async fetch(request: Request, requestContext?: RouterContextProvider) {
|
|
50
|
+
if (requestContext && !(requestContext instanceof RouterContextProvider)) {
|
|
51
|
+
requestContext = undefined;
|
|
52
|
+
}
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
const ssr = await import.meta.viteRsc.loadModule<
|
|
55
|
+
typeof import("./entry.ssr.tsx")
|
|
56
|
+
>("ssr", "index");
|
|
57
|
+
|
|
58
|
+
return await ssr.generateHTML(
|
|
59
|
+
request,
|
|
60
|
+
await fetchServer(request, requestContext),
|
|
61
|
+
);
|
|
62
|
+
},
|
|
63
|
+
};
|
|
42
64
|
|
|
43
65
|
if (import.meta.hot) {
|
|
44
66
|
import.meta.hot.accept();
|
|
@@ -1,31 +1,38 @@
|
|
|
1
1
|
import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
|
|
2
|
-
// @ts-expect-error
|
|
3
|
-
import
|
|
2
|
+
// @ts-expect-error - no types for this, can import from root once on latest 19
|
|
3
|
+
import { renderToReadableStream } from "react-dom/server.edge";
|
|
4
4
|
import {
|
|
5
|
-
unstable_RSCStaticRouter as RSCStaticRouter,
|
|
6
5
|
unstable_routeRSCServerRequest as routeRSCServerRequest,
|
|
6
|
+
unstable_RSCStaticRouter as RSCStaticRouter,
|
|
7
7
|
} from "react-router";
|
|
8
8
|
|
|
9
|
-
export
|
|
9
|
+
export async function generateHTML(
|
|
10
10
|
request: Request,
|
|
11
|
-
|
|
12
|
-
) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return routeRSCServerRequest({
|
|
11
|
+
serverResponse: Response,
|
|
12
|
+
): Promise<Response> {
|
|
13
|
+
return await routeRSCServerRequest({
|
|
14
|
+
// The incoming request.
|
|
17
15
|
request,
|
|
18
|
-
|
|
16
|
+
// The response from the RSC server.
|
|
17
|
+
serverResponse,
|
|
18
|
+
// Provide the React Server touchpoints.
|
|
19
19
|
createFromReadableStream,
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// Render the router to HTML.
|
|
21
|
+
async renderHTML(getPayload, options) {
|
|
22
|
+
const payload = await getPayload();
|
|
23
|
+
const formState =
|
|
24
|
+
payload.type === "render" ? await payload.formState : undefined;
|
|
25
|
+
|
|
26
|
+
const bootstrapScriptContent =
|
|
27
|
+
await import.meta.viteRsc.loadBootstrapScriptContent("index");
|
|
22
28
|
|
|
23
|
-
return
|
|
29
|
+
return await renderToReadableStream(
|
|
24
30
|
<RSCStaticRouter getPayload={getPayload} />,
|
|
25
31
|
{
|
|
32
|
+
...options,
|
|
26
33
|
bootstrapScriptContent,
|
|
34
|
+
formState,
|
|
27
35
|
signal: request.signal,
|
|
28
|
-
formState: await payload.formState,
|
|
29
36
|
},
|
|
30
37
|
);
|
|
31
38
|
},
|