@react-router/dev 0.0.0-experimental-4996fbe2b → 0.0.0-experimental-49eef6a01
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/bin.js +2 -0
- package/dist/cli/commands.js +1 -1
- package/dist/cli/detectPackageManager.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/run.js +1 -1
- package/dist/cli/useJavascript.js +1 -1
- package/dist/cli.js +1 -2
- package/dist/colors.js +1 -1
- package/dist/config/defaults/entry.server.node.tsx +12 -97
- package/dist/config/findConfig.js +1 -1
- package/dist/config/flatRoutes.js +1 -1
- package/dist/config/format.js +1 -1
- package/dist/config/routes.js +1 -1
- package/dist/config.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/invariant.js +1 -1
- package/dist/vite/babel.js +1 -1
- package/dist/vite/build.js +1 -1
- package/dist/vite/cloudflare-dev-proxy.d.ts +15 -0
- package/dist/vite/cloudflare-dev-proxy.js +73 -0
- package/dist/vite/define-route.d.ts +4 -1
- package/dist/vite/define-route.js +49 -14
- package/dist/vite/dev.js +1 -1
- package/dist/vite/import-vite-esm-sync.js +1 -1
- package/dist/vite/index.d.ts +1 -0
- package/dist/vite/index.js +8 -1
- package/dist/vite/node-adapter.js +1 -1
- package/dist/vite/plugin.js +88 -35
- package/dist/vite/profiler.js +1 -1
- package/dist/vite/remove-exports.js +1 -1
- package/dist/vite/resolve-file-url.js +1 -1
- package/dist/vite/styles.js +1 -1
- package/dist/vite/vmod.js +1 -1
- package/package.json +21 -7
package/bin.js
ADDED
package/dist/cli/commands.js
CHANGED
package/dist/cli/index.js
CHANGED
package/dist/cli/run.js
CHANGED
package/dist/cli.js
CHANGED
package/dist/colors.js
CHANGED
|
@@ -3,7 +3,8 @@ import { PassThrough } from "node:stream";
|
|
|
3
3
|
import type { AppLoadContext, EntryContext } from "react-router";
|
|
4
4
|
import { createReadableStreamFromReadable } from "@react-router/node";
|
|
5
5
|
import { ServerRouter } from "react-router";
|
|
6
|
-
import
|
|
6
|
+
import { isbot } from "isbot";
|
|
7
|
+
import type { RenderToPipeableStreamOptions } from "react-dom/server";
|
|
7
8
|
import { renderToPipeableStream } from "react-dom/server";
|
|
8
9
|
|
|
9
10
|
const ABORT_DELAY = 5_000;
|
|
@@ -12,114 +13,28 @@ export default function handleRequest(
|
|
|
12
13
|
request: Request,
|
|
13
14
|
responseStatusCode: number,
|
|
14
15
|
responseHeaders: Headers,
|
|
15
|
-
|
|
16
|
+
routerContext: EntryContext,
|
|
16
17
|
loadContext: AppLoadContext
|
|
17
|
-
) {
|
|
18
|
-
let prohibitOutOfOrderStreaming =
|
|
19
|
-
isBotRequest(request.headers.get("user-agent")) || remixContext.isSpaMode;
|
|
20
|
-
|
|
21
|
-
return prohibitOutOfOrderStreaming
|
|
22
|
-
? handleBotRequest(
|
|
23
|
-
request,
|
|
24
|
-
responseStatusCode,
|
|
25
|
-
responseHeaders,
|
|
26
|
-
remixContext
|
|
27
|
-
)
|
|
28
|
-
: handleBrowserRequest(
|
|
29
|
-
request,
|
|
30
|
-
responseStatusCode,
|
|
31
|
-
responseHeaders,
|
|
32
|
-
remixContext
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// We have some Remix apps in the wild already running with isbot@3 so we need
|
|
37
|
-
// to maintain backwards compatibility even though we want new apps to use
|
|
38
|
-
// isbot@4. That way, we can ship this as a minor Semver update to @react-router/dev.
|
|
39
|
-
function isBotRequest(userAgent: string | null) {
|
|
40
|
-
if (!userAgent) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// isbot >= 3.8.0, >4
|
|
45
|
-
if ("isbot" in isbotModule && typeof isbotModule.isbot === "function") {
|
|
46
|
-
return isbotModule.isbot(userAgent);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// isbot < 3.8.0
|
|
50
|
-
if ("default" in isbotModule && typeof isbotModule.default === "function") {
|
|
51
|
-
return isbotModule.default(userAgent);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function handleBotRequest(
|
|
58
|
-
request: Request,
|
|
59
|
-
responseStatusCode: number,
|
|
60
|
-
responseHeaders: Headers,
|
|
61
|
-
remixContext: EntryContext
|
|
62
18
|
) {
|
|
63
19
|
return new Promise((resolve, reject) => {
|
|
64
20
|
let shellRendered = false;
|
|
65
|
-
|
|
66
|
-
<ServerRouter
|
|
67
|
-
context={remixContext}
|
|
68
|
-
url={request.url}
|
|
69
|
-
abortDelay={ABORT_DELAY}
|
|
70
|
-
/>,
|
|
71
|
-
{
|
|
72
|
-
onAllReady() {
|
|
73
|
-
shellRendered = true;
|
|
74
|
-
const body = new PassThrough();
|
|
75
|
-
const stream = createReadableStreamFromReadable(body);
|
|
76
|
-
|
|
77
|
-
responseHeaders.set("Content-Type", "text/html");
|
|
78
|
-
|
|
79
|
-
resolve(
|
|
80
|
-
new Response(stream, {
|
|
81
|
-
headers: responseHeaders,
|
|
82
|
-
status: responseStatusCode,
|
|
83
|
-
})
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
pipe(body);
|
|
87
|
-
},
|
|
88
|
-
onShellError(error: unknown) {
|
|
89
|
-
reject(error);
|
|
90
|
-
},
|
|
91
|
-
onError(error: unknown) {
|
|
92
|
-
responseStatusCode = 500;
|
|
93
|
-
// Log streaming rendering errors from inside the shell. Don't log
|
|
94
|
-
// errors encountered during initial shell rendering since they'll
|
|
95
|
-
// reject and get logged in handleDocumentRequest.
|
|
96
|
-
if (shellRendered) {
|
|
97
|
-
console.error(error);
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
}
|
|
101
|
-
);
|
|
21
|
+
let userAgent = request.headers.get("user-agent");
|
|
102
22
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
23
|
+
// Ensure requests from bots and SPA Mode renders wait for all content to load before responding
|
|
24
|
+
// https://react.dev/reference/react-dom/server/renderToPipeableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation
|
|
25
|
+
let readyOption: keyof RenderToPipeableStreamOptions =
|
|
26
|
+
(userAgent && isbot(userAgent)) || routerContext.isSpaMode
|
|
27
|
+
? "onAllReady"
|
|
28
|
+
: "onShellReady";
|
|
106
29
|
|
|
107
|
-
function handleBrowserRequest(
|
|
108
|
-
request: Request,
|
|
109
|
-
responseStatusCode: number,
|
|
110
|
-
responseHeaders: Headers,
|
|
111
|
-
remixContext: EntryContext
|
|
112
|
-
) {
|
|
113
|
-
return new Promise((resolve, reject) => {
|
|
114
|
-
let shellRendered = false;
|
|
115
30
|
const { pipe, abort } = renderToPipeableStream(
|
|
116
31
|
<ServerRouter
|
|
117
|
-
context={
|
|
32
|
+
context={routerContext}
|
|
118
33
|
url={request.url}
|
|
119
34
|
abortDelay={ABORT_DELAY}
|
|
120
35
|
/>,
|
|
121
36
|
{
|
|
122
|
-
|
|
37
|
+
[readyOption]() {
|
|
123
38
|
shellRendered = true;
|
|
124
39
|
const body = new PassThrough();
|
|
125
40
|
const stream = createReadableStreamFromReadable(body);
|
package/dist/config/format.js
CHANGED
package/dist/config/routes.js
CHANGED
package/dist/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-experimental-
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-49eef6a01
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -232,11 +232,11 @@ async function resolveEntryFiles({
|
|
|
232
232
|
throw new Error(`Could not determine server runtime. Please install @react-router/node, or provide a custom entry.server.tsx/jsx file in your app directory.`);
|
|
233
233
|
}
|
|
234
234
|
if (!deps["isbot"]) {
|
|
235
|
-
console.log("adding `isbot` to your package.json, you should commit this change");
|
|
235
|
+
console.log("adding `isbot@5` to your package.json, you should commit this change");
|
|
236
236
|
pkgJson.update({
|
|
237
237
|
dependencies: {
|
|
238
238
|
...pkgJson.content.dependencies,
|
|
239
|
-
isbot: "^
|
|
239
|
+
isbot: "^5"
|
|
240
240
|
}
|
|
241
241
|
});
|
|
242
242
|
await pkgJson.save();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * as cli from "./cli/index";
|
|
2
2
|
export type { Manifest as AssetsManifest } from "./manifest";
|
|
3
3
|
export type { BuildManifest, Preset, ServerBundlesFunction, VitePluginConfig, } from "./config";
|
|
4
|
-
export { vitePlugin } from "./vite";
|
|
4
|
+
export { vitePlugin, cloudflareDevProxyVitePlugin } from "./vite";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-experimental-
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-49eef6a01
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -14,8 +14,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
14
14
|
|
|
15
15
|
var index = require('./cli/index.js');
|
|
16
16
|
var index$1 = require('./vite/index.js');
|
|
17
|
+
var cloudflareDevProxy = require('./vite/cloudflare-dev-proxy.js');
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
exports.cli = index;
|
|
21
22
|
exports.vitePlugin = index$1.vitePlugin;
|
|
23
|
+
exports.cloudflareDevProxyVitePlugin = cloudflareDevProxy.cloudflareDevProxyVitePlugin;
|
package/dist/invariant.js
CHANGED
package/dist/vite/babel.js
CHANGED
package/dist/vite/build.js
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type AppLoadContext } from "react-router";
|
|
2
|
+
import { type Plugin } from "vite";
|
|
3
|
+
import { type GetPlatformProxyOptions, type PlatformProxy } from "wrangler";
|
|
4
|
+
type CfProperties = Record<string, unknown>;
|
|
5
|
+
type LoadContext<Env, Cf extends CfProperties> = {
|
|
6
|
+
cloudflare: Omit<PlatformProxy<Env, Cf>, "dispose">;
|
|
7
|
+
};
|
|
8
|
+
type GetLoadContext<Env, Cf extends CfProperties> = (args: {
|
|
9
|
+
request: Request;
|
|
10
|
+
context: LoadContext<Env, Cf>;
|
|
11
|
+
}) => AppLoadContext | Promise<AppLoadContext>;
|
|
12
|
+
export declare const cloudflareDevProxyVitePlugin: <Env, Cf extends CfProperties>({ getLoadContext, ...options }?: {
|
|
13
|
+
getLoadContext?: GetLoadContext<Env, Cf>;
|
|
14
|
+
} & GetPlatformProxyOptions) => Plugin;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-49eef6a01
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
|
+
|
|
15
|
+
var reactRouter = require('react-router');
|
|
16
|
+
var wrangler = require('wrangler');
|
|
17
|
+
var nodeAdapter = require('./node-adapter.js');
|
|
18
|
+
|
|
19
|
+
let serverBuildId = "virtual:react-router/server-build";
|
|
20
|
+
const PLUGIN_NAME = "react-router-cloudflare-vite-dev-proxy";
|
|
21
|
+
const cloudflareDevProxyVitePlugin = ({
|
|
22
|
+
getLoadContext,
|
|
23
|
+
...options
|
|
24
|
+
} = {}) => {
|
|
25
|
+
return {
|
|
26
|
+
name: PLUGIN_NAME,
|
|
27
|
+
config: () => ({
|
|
28
|
+
ssr: {
|
|
29
|
+
resolve: {
|
|
30
|
+
externalConditions: ["workerd", "worker"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}),
|
|
34
|
+
configResolved: viteConfig => {
|
|
35
|
+
let pluginIndex = name => viteConfig.plugins.findIndex(plugin => plugin.name === name);
|
|
36
|
+
let reactRouterPluginIndex = pluginIndex("react-router");
|
|
37
|
+
if (reactRouterPluginIndex >= 0 && reactRouterPluginIndex < pluginIndex(PLUGIN_NAME)) {
|
|
38
|
+
throw new Error(`The "${PLUGIN_NAME}" plugin should be placed before the React Router plugin in your Vite config file`);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
configureServer: async viteDevServer => {
|
|
42
|
+
// Do not include `dispose` in Cloudflare context
|
|
43
|
+
let {
|
|
44
|
+
dispose,
|
|
45
|
+
...cloudflare
|
|
46
|
+
} = await wrangler.getPlatformProxy(options);
|
|
47
|
+
let context = {
|
|
48
|
+
cloudflare
|
|
49
|
+
};
|
|
50
|
+
return () => {
|
|
51
|
+
if (!viteDevServer.config.server.middlewareMode) {
|
|
52
|
+
viteDevServer.middlewares.use(async (nodeReq, nodeRes, next) => {
|
|
53
|
+
try {
|
|
54
|
+
let build = await viteDevServer.ssrLoadModule(serverBuildId);
|
|
55
|
+
let handler = reactRouter.createRequestHandler(build, "development");
|
|
56
|
+
let req = nodeAdapter.fromNodeRequest(nodeReq);
|
|
57
|
+
let loadContext = getLoadContext ? await getLoadContext({
|
|
58
|
+
request: req,
|
|
59
|
+
context
|
|
60
|
+
}) : context;
|
|
61
|
+
let res = await handler(req, loadContext);
|
|
62
|
+
await nodeAdapter.toNodeRequest(res, nodeRes);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
next(error);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
exports.cloudflareDevProxyVitePlugin = cloudflareDevProxyVitePlugin;
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
export declare function transform(code: string
|
|
1
|
+
export declare function transform(code: string, id: string, options?: {
|
|
2
|
+
ssr?: boolean;
|
|
3
|
+
}): string | import("@babel/generator").GeneratorResult;
|
|
4
|
+
export declare function parseFields(code: string): string[];
|
|
2
5
|
export declare function assertNotImported(code: string): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-experimental-
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-49eef6a01
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
14
|
|
|
15
15
|
var babel$1 = require('@babel/core');
|
|
16
|
+
var babelDeadCodeElimination = require('babel-dead-code-elimination');
|
|
16
17
|
var babel = require('./babel.js');
|
|
17
18
|
var t = require('@babel/types');
|
|
18
19
|
var parser = require('@babel/parser');
|
|
@@ -38,23 +39,41 @@ function _interopNamespace(e) {
|
|
|
38
39
|
var babel__namespace = /*#__PURE__*/_interopNamespace(babel$1);
|
|
39
40
|
var t__namespace = /*#__PURE__*/_interopNamespace(t);
|
|
40
41
|
|
|
41
|
-
function transform(code) {
|
|
42
|
+
function transform(code, id, options = {}) {
|
|
43
|
+
if (options !== null && options !== void 0 && options.ssr) return code;
|
|
42
44
|
let ast = parse(code);
|
|
45
|
+
let refs = babelDeadCodeElimination.findReferencedIdentifiers(ast);
|
|
46
|
+
let markedForRemoval = [];
|
|
47
|
+
assertDefineRouteOnlyAfterExportDefault(ast);
|
|
43
48
|
babel.traverse(ast, {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
throw path.buildCodeFrameError("`defineRoute` must be a function call immediately after `export default`");
|
|
49
|
+
ExportDefaultDeclaration(path) {
|
|
50
|
+
let analysis = analyzeRouteExport(path);
|
|
51
|
+
for (let [key, fieldPath] of Object.entries(analysis)) {
|
|
52
|
+
if (["headers", "serverLoader", "serverAction"].includes(key)) {
|
|
53
|
+
if (!fieldPath) continue;
|
|
54
|
+
markedForRemoval.push(fieldPath);
|
|
55
|
+
}
|
|
52
56
|
}
|
|
53
|
-
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
markedForRemoval.forEach(path => path.remove());
|
|
60
|
+
babelDeadCodeElimination.deadCodeElimination(ast, refs);
|
|
61
|
+
return babel.generate(ast, {
|
|
62
|
+
sourceMaps: true,
|
|
63
|
+
sourceFileName: id
|
|
64
|
+
}, code);
|
|
65
|
+
}
|
|
66
|
+
function parseFields(code) {
|
|
67
|
+
let fields = [];
|
|
68
|
+
let ast = parse(code);
|
|
69
|
+
assertDefineRouteOnlyAfterExportDefault(ast);
|
|
70
|
+
babel.traverse(ast, {
|
|
54
71
|
ExportDefaultDeclaration(path) {
|
|
55
|
-
analyzeRouteExport(path);
|
|
72
|
+
let analysis = analyzeRouteExport(path);
|
|
73
|
+
fields = Object.keys(analysis);
|
|
56
74
|
}
|
|
57
75
|
});
|
|
76
|
+
return fields;
|
|
58
77
|
}
|
|
59
78
|
function analyzeRouteExport(path) {
|
|
60
79
|
let route = path.node.declaration;
|
|
@@ -82,6 +101,7 @@ function analyzeRouteExport(path) {
|
|
|
82
101
|
throw path.get("declaration").buildCodeFrameError("Default export of a route module must be either a literal object or a call to `defineRoute`");
|
|
83
102
|
}
|
|
84
103
|
function analyzeRoute(path) {
|
|
104
|
+
let analysis = {};
|
|
85
105
|
for (let [i, property] of path.node.properties.entries()) {
|
|
86
106
|
// spread: defineRoute({ ...dynamic })
|
|
87
107
|
if (!t__namespace.isObjectProperty(property) && !t__namespace.isObjectMethod(property)) {
|
|
@@ -109,10 +129,10 @@ function analyzeRoute(path) {
|
|
|
109
129
|
throw elementPath.buildCodeFrameError("Route param must be a literal string");
|
|
110
130
|
}
|
|
111
131
|
}
|
|
112
|
-
continue;
|
|
113
132
|
}
|
|
133
|
+
analysis[key] = propertyPath;
|
|
114
134
|
}
|
|
115
|
-
|
|
135
|
+
return analysis;
|
|
116
136
|
}
|
|
117
137
|
function assertNotImported(code) {
|
|
118
138
|
let ast = parse(code);
|
|
@@ -142,6 +162,20 @@ function parse(source) {
|
|
|
142
162
|
});
|
|
143
163
|
return ast;
|
|
144
164
|
}
|
|
165
|
+
function assertDefineRouteOnlyAfterExportDefault(ast) {
|
|
166
|
+
babel.traverse(ast, {
|
|
167
|
+
Identifier(path) {
|
|
168
|
+
if (!isDefineRoute(path)) return;
|
|
169
|
+
if (t__namespace.isImportSpecifier(path.parent)) return;
|
|
170
|
+
if (!t__namespace.isCallExpression(path.parent)) {
|
|
171
|
+
throw path.buildCodeFrameError("`defineRoute` must be a function call immediately after `export default`");
|
|
172
|
+
}
|
|
173
|
+
if (!t__namespace.isExportDefaultDeclaration(path.parentPath.parent)) {
|
|
174
|
+
throw path.buildCodeFrameError("`defineRoute` must be a function call immediately after `export default`");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
145
179
|
function isDefineRoute(path) {
|
|
146
180
|
if (!t__namespace.isIdentifier(path.node)) return false;
|
|
147
181
|
let binding = path.scope.getBinding(path.node.name);
|
|
@@ -169,4 +203,5 @@ function isCanonicallyImportedAs(binding, {
|
|
|
169
203
|
}
|
|
170
204
|
|
|
171
205
|
exports.assertNotImported = assertNotImported;
|
|
206
|
+
exports.parseFields = parseFields;
|
|
172
207
|
exports.transform = transform;
|
package/dist/vite/dev.js
CHANGED
package/dist/vite/index.d.ts
CHANGED
package/dist/vite/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-experimental-
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-49eef6a01
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
|
|
13
13
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
14
|
|
|
15
|
+
require('react-router');
|
|
16
|
+
require('wrangler');
|
|
17
|
+
require('node:events');
|
|
18
|
+
require('node:stream');
|
|
19
|
+
require('set-cookie-parser');
|
|
20
|
+
require('@react-router/node');
|
|
21
|
+
|
|
15
22
|
const vitePlugin = (...args) => {
|
|
16
23
|
let {
|
|
17
24
|
reactRouterVitePlugin
|
package/dist/vite/plugin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v0.0.0-experimental-
|
|
2
|
+
* @react-router/dev v0.0.0-experimental-49eef6a01
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -108,11 +108,11 @@ async function loadPluginContext({
|
|
|
108
108
|
}
|
|
109
109
|
const SERVER_ONLY_ROUTE_EXPORTS = ["loader", "action", "headers"];
|
|
110
110
|
const CLIENT_ROUTE_EXPORTS = ["clientAction", "clientLoader", "default", "ErrorBoundary", "handle", "HydrateFallback", "Layout", "links", "meta", "shouldRevalidate"];
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
// Each route gets its own virtual module marked with an entry query string
|
|
112
|
+
const ROUTE_ENTRY_QUERY_STRING = "?route-entry=1";
|
|
113
|
+
const isRouteEntry = id => {
|
|
114
|
+
return id.endsWith(ROUTE_ENTRY_QUERY_STRING);
|
|
115
|
+
};
|
|
116
116
|
let serverBuildId = vmod.id("server-build");
|
|
117
117
|
let serverManifestId = vmod.id("server-manifest");
|
|
118
118
|
let browserManifestId = vmod.id("browser-manifest");
|
|
@@ -140,7 +140,7 @@ const getHash = (source, maxLength) => {
|
|
|
140
140
|
const resolveChunk = (ctx, viteManifest, absoluteFilePath) => {
|
|
141
141
|
let vite = importViteEsmSync.importViteEsmSync();
|
|
142
142
|
let rootRelativeFilePath = vite.normalizePath(path__namespace.relative(ctx.rootDirectory, absoluteFilePath));
|
|
143
|
-
let entryChunk = viteManifest[rootRelativeFilePath +
|
|
143
|
+
let entryChunk = viteManifest[rootRelativeFilePath + ROUTE_ENTRY_QUERY_STRING] ?? viteManifest[rootRelativeFilePath];
|
|
144
144
|
if (!entryChunk) {
|
|
145
145
|
let knownManifestKeys = Object.keys(viteManifest).map(key => '"' + key + '"').join(", ");
|
|
146
146
|
throw new Error(`No manifest entry found for "${rootRelativeFilePath}". Known manifest keys: ${knownManifestKeys}`);
|
|
@@ -195,6 +195,20 @@ const getRouteManifestModuleExports = async (viteChildCompiler, ctx) => {
|
|
|
195
195
|
return Object.fromEntries(entries);
|
|
196
196
|
};
|
|
197
197
|
const getRouteModuleExports = async (viteChildCompiler, ctx, routeFile, readRouteFile) => {
|
|
198
|
+
let routePath = path__namespace.resolve(ctx.reactRouterConfig.appDirectory, routeFile);
|
|
199
|
+
let code = await ((readRouteFile === null || readRouteFile === void 0 ? void 0 : readRouteFile()) ?? fse__namespace.readFile(routePath, "utf-8"));
|
|
200
|
+
if (!code.includes("defineRoute")) {
|
|
201
|
+
return _getRouteModuleExports(viteChildCompiler, ctx, routeFile, readRouteFile);
|
|
202
|
+
}
|
|
203
|
+
let renameFields = ["Component", "serverLoader", "actionLoader"];
|
|
204
|
+
let fields = defineRoute.parseFields(code);
|
|
205
|
+
let exports = fields.filter(exportName => !renameFields.includes(exportName));
|
|
206
|
+
if (fields.includes("Component")) exports.push("default");
|
|
207
|
+
if (fields.includes("serverLoader")) exports.push("loader");
|
|
208
|
+
if (fields.includes("serverAction")) exports.push("action");
|
|
209
|
+
return exports;
|
|
210
|
+
};
|
|
211
|
+
const _getRouteModuleExports = async (viteChildCompiler, ctx, routeFile, readRouteFile) => {
|
|
198
212
|
if (!viteChildCompiler) {
|
|
199
213
|
throw new Error("Vite child compiler not found");
|
|
200
214
|
}
|
|
@@ -320,7 +334,7 @@ const reactRouterVitePlugin = _config => {
|
|
|
320
334
|
import * as entryServer from ${JSON.stringify(resolveFileUrl.resolveFileUrl(ctx, ctx.entryServerFilePath))};
|
|
321
335
|
${Object.keys(routes).map((key, index) => {
|
|
322
336
|
let route = routes[key];
|
|
323
|
-
return `import * as route${index} from ${JSON.stringify(resolveFileUrl.resolveFileUrl(ctx, resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)))};`;
|
|
337
|
+
return `import * as route${index} from ${JSON.stringify(resolveFileUrl.resolveFileUrl(ctx, resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)) + ROUTE_ENTRY_QUERY_STRING)};`;
|
|
324
338
|
}).join("\n")}
|
|
325
339
|
export { default as assets } from ${JSON.stringify(serverManifestId)};
|
|
326
340
|
export const assetsBuildDirectory = ${JSON.stringify(path__namespace.relative(ctx.rootDirectory, getClientBuildDirectory(ctx.reactRouterConfig)))};
|
|
@@ -434,7 +448,7 @@ const reactRouterVitePlugin = _config => {
|
|
|
434
448
|
path: route.path,
|
|
435
449
|
index: route.index,
|
|
436
450
|
caseSensitive: route.caseSensitive,
|
|
437
|
-
module: path__namespace.posix.join(ctx.publicPath, `${resolveFileUrl.resolveFileUrl(ctx, resolveRelativeRouteFilePath(route, ctx.reactRouterConfig))}`),
|
|
451
|
+
module: path__namespace.posix.join(ctx.publicPath, `${resolveFileUrl.resolveFileUrl(ctx, resolveRelativeRouteFilePath(route, ctx.reactRouterConfig))}${ROUTE_ENTRY_QUERY_STRING}`),
|
|
438
452
|
hasAction: sourceExports.includes("action"),
|
|
439
453
|
hasLoader: sourceExports.includes("loader"),
|
|
440
454
|
hasClientAction: sourceExports.includes("clientAction"),
|
|
@@ -496,7 +510,7 @@ const reactRouterVitePlugin = _config => {
|
|
|
496
510
|
// This is only needed within this repo because these packages
|
|
497
511
|
// are linked to a directory outside of node_modules so Vite
|
|
498
512
|
// treats them as internal code by default.
|
|
499
|
-
"react-router", "react-router-dom", "@react-router/dev", "@react-router/express", "@react-router/node", "@react-router/serve"] : undefined
|
|
513
|
+
"react-router", "react-router-dom", "@react-router/cloudflare", "@react-router/dev", "@react-router/express", "@react-router/node", "@react-router/serve"] : undefined
|
|
500
514
|
},
|
|
501
515
|
optimizeDeps: {
|
|
502
516
|
include: [
|
|
@@ -540,7 +554,7 @@ const reactRouterVitePlugin = _config => {
|
|
|
540
554
|
rollupOptions: {
|
|
541
555
|
...baseRollupOptions,
|
|
542
556
|
preserveEntrySignatures: "exports-only",
|
|
543
|
-
input: [ctx.entryClientFilePath, ...Object.values(ctx.reactRouterConfig.routes).map(route => `${path__namespace.resolve(ctx.reactRouterConfig.appDirectory, route.file)}${
|
|
557
|
+
input: [ctx.entryClientFilePath, ...Object.values(ctx.reactRouterConfig.routes).map(route => `${path__namespace.resolve(ctx.reactRouterConfig.appDirectory, route.file)}${ROUTE_ENTRY_QUERY_STRING}`)]
|
|
544
558
|
}
|
|
545
559
|
} : {
|
|
546
560
|
// We move SSR-only assets to client assets. Note that the
|
|
@@ -637,13 +651,6 @@ const reactRouterVitePlugin = _config => {
|
|
|
637
651
|
if (styles.isCssModulesFile(id)) {
|
|
638
652
|
cssModulesManifest[id] = code;
|
|
639
653
|
}
|
|
640
|
-
if (id.endsWith(BUILD_CLIENT_ROUTE_QUERY_STRING)) {
|
|
641
|
-
let routeModuleId = id.replace(BUILD_CLIENT_ROUTE_QUERY_STRING, "");
|
|
642
|
-
let sourceExports = await getRouteModuleExports(viteChildCompiler, ctx, routeModuleId);
|
|
643
|
-
let routeFileName = path__namespace.basename(routeModuleId);
|
|
644
|
-
let clientExports = sourceExports.filter(exportName => CLIENT_ROUTE_EXPORTS.includes(exportName)).join(", ");
|
|
645
|
-
return `export { ${clientExports} } from "./${routeFileName}";`;
|
|
646
|
-
}
|
|
647
654
|
},
|
|
648
655
|
buildStart() {
|
|
649
656
|
invariant["default"](viteConfig);
|
|
@@ -770,6 +777,34 @@ const reactRouterVitePlugin = _config => {
|
|
|
770
777
|
var _viteChildCompiler;
|
|
771
778
|
await ((_viteChildCompiler = viteChildCompiler) === null || _viteChildCompiler === void 0 ? void 0 : _viteChildCompiler.close());
|
|
772
779
|
}
|
|
780
|
+
}, {
|
|
781
|
+
name: "react-router-route-entry",
|
|
782
|
+
enforce: "pre",
|
|
783
|
+
async transform(code, id, options) {
|
|
784
|
+
if (!isRouteEntry(id)) return;
|
|
785
|
+
let routeModuleId = id.replace(ROUTE_ENTRY_QUERY_STRING, "");
|
|
786
|
+
let routeFileName = path__namespace.basename(routeModuleId);
|
|
787
|
+
if (!code.includes("defineRoute")) {
|
|
788
|
+
let sourceExports = await getRouteModuleExports(viteChildCompiler, ctx, routeModuleId);
|
|
789
|
+
let reexports = sourceExports.filter(exportName => (options === null || options === void 0 ? void 0 : options.ssr) && SERVER_ONLY_ROUTE_EXPORTS.includes(exportName) || CLIENT_ROUTE_EXPORTS.includes(exportName)).join(", ");
|
|
790
|
+
return `export { ${reexports} } from "./${routeFileName}";`;
|
|
791
|
+
}
|
|
792
|
+
let renameFields = ["Component", "serverLoader", "serverAction"];
|
|
793
|
+
let fields = defineRoute.parseFields(code);
|
|
794
|
+
let reexports = fields.filter(exportName => !renameFields.includes(exportName)).filter(exportName => (options === null || options === void 0 ? void 0 : options.ssr) && SERVER_ONLY_ROUTE_EXPORTS.includes(exportName) || CLIENT_ROUTE_EXPORTS.includes(exportName)).map(reexport => `export const ${reexport} = route.${reexport};`);
|
|
795
|
+
let content = `import route from "./${routeFileName}";`;
|
|
796
|
+
if (fields.includes("Component")) {
|
|
797
|
+
content += `\n` + [`import { createElement } from "react";`, `import { useParams, useLoaderData, useActionData } from "react-router";`, `export default function Route() {`, ` let params = useParams();`, ` let loaderData = useLoaderData();`, ` let actionData = useActionData();`, ` return createElement(route.Component, { params, loaderData, actionData });`, `}`].join("\n");
|
|
798
|
+
}
|
|
799
|
+
if (options !== null && options !== void 0 && options.ssr && fields.includes("serverLoader")) {
|
|
800
|
+
content += `\nexport const loader = route.serverLoader;`;
|
|
801
|
+
}
|
|
802
|
+
if (options !== null && options !== void 0 && options.ssr && fields.includes("serverAction")) {
|
|
803
|
+
content += `\nexport const action = route.serverAction;`;
|
|
804
|
+
}
|
|
805
|
+
content += "\n" + reexports.join("\n");
|
|
806
|
+
return content;
|
|
807
|
+
}
|
|
773
808
|
}, {
|
|
774
809
|
name: "react-router-virtual-modules",
|
|
775
810
|
enforce: "pre",
|
|
@@ -807,13 +842,13 @@ const reactRouterVitePlugin = _config => {
|
|
|
807
842
|
enforce: "pre",
|
|
808
843
|
async transform(code, id, options) {
|
|
809
844
|
if (options !== null && options !== void 0 && options.ssr) return;
|
|
810
|
-
if (
|
|
845
|
+
if (!code.includes("defineRoute")) return; // temporary back compat, remove once old style routes are unsupported
|
|
846
|
+
if (id.endsWith(ROUTE_ENTRY_QUERY_STRING)) return;
|
|
811
847
|
let route = getRoute(ctx.reactRouterConfig, id);
|
|
812
848
|
if (!route && code.includes("defineRoute")) {
|
|
813
849
|
return defineRoute.assertNotImported(code);
|
|
814
850
|
}
|
|
815
|
-
|
|
816
|
-
defineRoute.transform(code);
|
|
851
|
+
return defineRoute.transform(code, id, options);
|
|
817
852
|
}
|
|
818
853
|
}, {
|
|
819
854
|
name: "react-router-dot-server",
|
|
@@ -928,6 +963,11 @@ const reactRouterVitePlugin = _config => {
|
|
|
928
963
|
let isJSX = filepath.endsWith("x");
|
|
929
964
|
let useFastRefresh = !ssr && (isJSX || code.includes(devRuntime));
|
|
930
965
|
if (!useFastRefresh) return;
|
|
966
|
+
if (isRouteEntry(id)) {
|
|
967
|
+
return {
|
|
968
|
+
code: addRefreshWrapper(ctx.reactRouterConfig, code, id)
|
|
969
|
+
};
|
|
970
|
+
}
|
|
931
971
|
let result = await babel__default["default"].transformAsync(code, {
|
|
932
972
|
babelrc: false,
|
|
933
973
|
configFile: false,
|
|
@@ -996,7 +1036,7 @@ function isEqualJson(v1, v2) {
|
|
|
996
1036
|
}
|
|
997
1037
|
function addRefreshWrapper(reactRouterConfig, code, id) {
|
|
998
1038
|
let route = getRoute(reactRouterConfig, id);
|
|
999
|
-
let acceptExports = route ? ["clientAction", "clientLoader", "handle", "meta", "links", "shouldRevalidate"] : [];
|
|
1039
|
+
let acceptExports = route || isRouteEntry(id) ? ["clientAction", "clientLoader", "handle", "meta", "links", "shouldRevalidate"] : [];
|
|
1000
1040
|
return REACT_REFRESH_HEADER.replaceAll("__SOURCE__", JSON.stringify(id)) + code + REACT_REFRESH_FOOTER.replaceAll("__SOURCE__", JSON.stringify(id)).replaceAll("__ACCEPT_EXPORTS__", JSON.stringify(acceptExports)).replaceAll("__ROUTE_ID__", JSON.stringify(route === null || route === void 0 ? void 0 : route.id));
|
|
1001
1041
|
}
|
|
1002
1042
|
const REACT_REFRESH_HEADER = `
|
|
@@ -1106,19 +1146,20 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
|
|
|
1106
1146
|
}
|
|
1107
1147
|
await prerenderRoute(handler, path, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit);
|
|
1108
1148
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1149
|
+
await prerenderManifest(build, clientBuildDirectory, reactRouterConfig, viteConfig);
|
|
1150
|
+
}
|
|
1151
|
+
async function prerenderData(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
1152
|
+
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath === "/" ? "/_root.data" : `${prerenderPath.replace(/\/$/, "")}.data`}`.replace(/\/\/+/g, "/");
|
|
1153
|
+
let request = new Request(`http://localhost${normalizedPath}`, requestInit);
|
|
1154
|
+
let response = await handler(request);
|
|
1155
|
+
let data = await response.text();
|
|
1156
|
+
validatePrerenderedResponse(response, data, "Prerender", normalizedPath);
|
|
1157
|
+
// Write out the .data file
|
|
1158
|
+
let outdir = path__namespace.relative(process.cwd(), clientBuildDirectory);
|
|
1159
|
+
let outfile = path__namespace.join(outdir, ...normalizedPath.split("/"));
|
|
1160
|
+
await fse__namespace.ensureDir(path__namespace.dirname(outfile));
|
|
1161
|
+
await fse__namespace.outputFile(outfile, data);
|
|
1162
|
+
viteConfig.logger.info(`Prerender: Generated ${colors__default["default"].bold(outfile)}`);
|
|
1122
1163
|
}
|
|
1123
1164
|
async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
1124
1165
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath}/`.replace(/\/\/+/g, "/");
|
|
@@ -1136,6 +1177,18 @@ async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reac
|
|
|
1136
1177
|
await fse__namespace.outputFile(outfile, html);
|
|
1137
1178
|
viteConfig.logger.info(`Prerender: Generated ${colors__default["default"].bold(outfile)}`);
|
|
1138
1179
|
}
|
|
1180
|
+
async function prerenderManifest(build, clientBuildDirectory, reactRouterConfig, viteConfig) {
|
|
1181
|
+
let normalizedPath = `${reactRouterConfig.basename}/__manifest`.replace(/\/\/+/g, "/");
|
|
1182
|
+
let outdir = path__namespace.relative(process.cwd(), clientBuildDirectory);
|
|
1183
|
+
let outfile = path__namespace.join(outdir, ...normalizedPath.split("/"));
|
|
1184
|
+
await fse__namespace.ensureDir(path__namespace.dirname(outfile));
|
|
1185
|
+
let manifestData = JSON.stringify({
|
|
1186
|
+
notFoundPaths: [],
|
|
1187
|
+
patches: build.assets.routes
|
|
1188
|
+
});
|
|
1189
|
+
await fse__namespace.outputFile(outfile, manifestData);
|
|
1190
|
+
viteConfig.logger.info(`Prerender: Generated ${colors__default["default"].bold(outfile)}`);
|
|
1191
|
+
}
|
|
1139
1192
|
function validatePrerenderedResponse(response, html, prefix, path) {
|
|
1140
1193
|
if (response.status !== 200) {
|
|
1141
1194
|
throw new Error(`${prefix}: Received a ${response.status} status code from ` + `\`entry.server.tsx\` while prerendering the \`${path}\` ` + `path.\n${html}`);
|
package/dist/vite/profiler.js
CHANGED
package/dist/vite/styles.js
CHANGED
package/dist/vite/vmod.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/dev",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-49eef6a01",
|
|
4
4
|
"description": "Dev tools and CLI for React Router",
|
|
5
5
|
"homepage": "https://reactrouter.com",
|
|
6
6
|
"bugs": {
|
|
@@ -14,8 +14,15 @@
|
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"main": "dist/index.js",
|
|
16
16
|
"typings": "dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
17
24
|
"bin": {
|
|
18
|
-
"react-router": "
|
|
25
|
+
"react-router": "bin.js"
|
|
19
26
|
},
|
|
20
27
|
"dependencies": {
|
|
21
28
|
"@babel/core": "^7.21.8",
|
|
@@ -28,6 +35,7 @@
|
|
|
28
35
|
"@babel/types": "^7.22.5",
|
|
29
36
|
"@npmcli/package-json": "^4.0.1",
|
|
30
37
|
"arg": "^5.0.1",
|
|
38
|
+
"babel-dead-code-elimination": "^1.0.6",
|
|
31
39
|
"chalk": "^4.1.2",
|
|
32
40
|
"es-module-lexer": "^1.3.1",
|
|
33
41
|
"exit-hook": "2.2.1",
|
|
@@ -42,7 +50,7 @@
|
|
|
42
50
|
"react-refresh": "^0.14.0",
|
|
43
51
|
"semver": "^7.3.7",
|
|
44
52
|
"set-cookie-parser": "^2.6.0",
|
|
45
|
-
"@react-router/node": "0.0.0-experimental-
|
|
53
|
+
"@react-router/node": "0.0.0-experimental-49eef6a01"
|
|
46
54
|
},
|
|
47
55
|
"devDependencies": {
|
|
48
56
|
"@types/babel__core": "^7.20.5",
|
|
@@ -66,14 +74,16 @@
|
|
|
66
74
|
"strip-ansi": "^6.0.1",
|
|
67
75
|
"tiny-invariant": "^1.2.0",
|
|
68
76
|
"vite": "^5.1.0",
|
|
69
|
-
"
|
|
70
|
-
"react-router": "
|
|
77
|
+
"wrangler": "^3.28.2",
|
|
78
|
+
"@react-router/serve": "0.0.0-experimental-49eef6a01",
|
|
79
|
+
"react-router": "^0.0.0-experimental-49eef6a01"
|
|
71
80
|
},
|
|
72
81
|
"peerDependencies": {
|
|
73
82
|
"typescript": "^5.1.0",
|
|
74
83
|
"vite": "^5.1.0",
|
|
75
|
-
"
|
|
76
|
-
"react-router": "^0.0.0-experimental-
|
|
84
|
+
"wrangler": "^3.28.2",
|
|
85
|
+
"@react-router/serve": "^0.0.0-experimental-49eef6a01",
|
|
86
|
+
"react-router": "^0.0.0-experimental-49eef6a01"
|
|
77
87
|
},
|
|
78
88
|
"peerDependenciesMeta": {
|
|
79
89
|
"@react-router/serve": {
|
|
@@ -81,6 +91,9 @@
|
|
|
81
91
|
},
|
|
82
92
|
"typescript": {
|
|
83
93
|
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"wrangler": {
|
|
96
|
+
"optional": true
|
|
84
97
|
}
|
|
85
98
|
},
|
|
86
99
|
"engines": {
|
|
@@ -88,6 +101,7 @@
|
|
|
88
101
|
},
|
|
89
102
|
"files": [
|
|
90
103
|
"dist/",
|
|
104
|
+
"bin.js",
|
|
91
105
|
"CHANGELOG.md",
|
|
92
106
|
"LICENSE.md",
|
|
93
107
|
"README.md"
|