@umijs/server 4.0.0-canary.20240305.1 → 4.0.0-canary.20240402.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/dist/ssr.d.ts +14 -2
- package/dist/ssr.js +201 -62
- package/dist/types.d.ts +44 -0
- package/package.json +2 -2
package/dist/ssr.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
/// <reference lib="webworker" />
|
|
2
|
+
import type { RequestHandler } from '@umijs/bundler-utils/compiled/express';
|
|
1
3
|
import React from 'react';
|
|
2
|
-
import type { UmiRequest } from './types';
|
|
4
|
+
import type { ITplOpts, UmiRequest } from './types';
|
|
3
5
|
interface RouteLoaders {
|
|
4
6
|
[key: string]: () => Promise<any>;
|
|
5
7
|
}
|
|
@@ -25,9 +27,19 @@ interface CreateRequestHandlerOptions extends CreateRequestServerlessOptions {
|
|
|
25
27
|
createHistory: (opts: any) => any;
|
|
26
28
|
helmetContext?: any;
|
|
27
29
|
ServerInsertedHTMLContext: React.Context<ServerInsertedHTMLHook | null>;
|
|
30
|
+
tplOpts: ITplOpts;
|
|
31
|
+
renderFromRoot: boolean;
|
|
32
|
+
mountElementId: string;
|
|
28
33
|
}
|
|
29
34
|
export declare function createMarkupGenerator(opts: CreateRequestHandlerOptions): (url: string) => Promise<unknown>;
|
|
30
|
-
|
|
35
|
+
declare type IExpressRequestHandlerArgs = Parameters<RequestHandler>;
|
|
36
|
+
declare type IWorkerRequestHandlerArgs = [
|
|
37
|
+
ev: FetchEvent,
|
|
38
|
+
opts?: {
|
|
39
|
+
modifyResponse?: (res: Response) => Promise<Response> | Response;
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
export default function createRequestHandler(opts: CreateRequestHandlerOptions): (...args: IExpressRequestHandlerArgs | IWorkerRequestHandlerArgs) => Promise<void>;
|
|
31
43
|
export declare function createUmiHandler(opts: CreateRequestHandlerOptions): (req: UmiRequest, params?: CreateRequestHandlerOptions) => Promise<NodeJS.ReadableStream>;
|
|
32
44
|
export declare function createUmiServerLoader(opts: CreateRequestHandlerOptions): (req: UmiRequest) => Promise<any>;
|
|
33
45
|
export {};
|
package/dist/ssr.js
CHANGED
|
@@ -39,7 +39,8 @@ var import_react = __toESM(require("react"));
|
|
|
39
39
|
var ReactDomServer = __toESM(require("react-dom/server"));
|
|
40
40
|
var import_react_router_dom = require("react-router-dom");
|
|
41
41
|
var import_stream = require("stream");
|
|
42
|
-
var createJSXProvider = (Provider
|
|
42
|
+
var createJSXProvider = (Provider) => {
|
|
43
|
+
const serverInsertedHTMLCallbacks = /* @__PURE__ */ new Set();
|
|
43
44
|
const JSXProvider = (props) => {
|
|
44
45
|
const addInsertedHtml = import_react.default.useCallback(
|
|
45
46
|
(handler) => {
|
|
@@ -52,7 +53,7 @@ var createJSXProvider = (Provider, serverInsertedHTMLCallbacks) => {
|
|
|
52
53
|
value: addInsertedHtml
|
|
53
54
|
});
|
|
54
55
|
};
|
|
55
|
-
return JSXProvider;
|
|
56
|
+
return [JSXProvider, serverInsertedHTMLCallbacks];
|
|
56
57
|
};
|
|
57
58
|
function createJSXGenerator(opts) {
|
|
58
59
|
return async (url, serverLoaderArgs) => {
|
|
@@ -84,7 +85,6 @@ function createJSXGenerator(opts) {
|
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
86
87
|
const loaderData = {};
|
|
87
|
-
const metadata = {};
|
|
88
88
|
await Promise.all(
|
|
89
89
|
matches.filter((id) => routes[id].hasServerLoader).map(
|
|
90
90
|
(id) => new Promise(async (resolve) => {
|
|
@@ -94,15 +94,19 @@ function createJSXGenerator(opts) {
|
|
|
94
94
|
serverLoaderArgs
|
|
95
95
|
});
|
|
96
96
|
if (routes[id].hasMetadataLoader) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
97
|
+
const metadataLoaderData = await executeMetadataLoader({
|
|
98
|
+
routesWithServerLoader,
|
|
99
|
+
routeKey: id,
|
|
100
|
+
serverLoaderArgs,
|
|
101
|
+
serverLoaderData: loaderData[id]
|
|
102
|
+
});
|
|
103
|
+
Object.entries(metadataLoaderData).forEach(([k, v]) => {
|
|
104
|
+
if (Array.isArray(v)) {
|
|
105
|
+
opts.tplOpts[k] = (opts.tplOpts[k] || []).concat(v);
|
|
106
|
+
} else {
|
|
107
|
+
opts.tplOpts[k] = v;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
106
110
|
}
|
|
107
111
|
resolve();
|
|
108
112
|
})
|
|
@@ -116,7 +120,9 @@ function createJSXGenerator(opts) {
|
|
|
116
120
|
location: url,
|
|
117
121
|
manifest,
|
|
118
122
|
loaderData,
|
|
119
|
-
|
|
123
|
+
tplOpts: opts.tplOpts,
|
|
124
|
+
renderFromRoot: opts.renderFromRoot,
|
|
125
|
+
mountElementId: opts.mountElementId
|
|
120
126
|
};
|
|
121
127
|
const element = await opts.getClientRootComponent(
|
|
122
128
|
context
|
|
@@ -127,13 +133,19 @@ function createJSXGenerator(opts) {
|
|
|
127
133
|
};
|
|
128
134
|
};
|
|
129
135
|
}
|
|
130
|
-
var
|
|
136
|
+
var SERVER_INSERTED_HTML = "umi-server-inserted-html";
|
|
137
|
+
var getGenerateStaticHTML = (serverInsertedHTMLCallbacks, opts) => {
|
|
138
|
+
const children = import_react.default.createElement(import_react.default.Fragment, {
|
|
139
|
+
children: Array.from(serverInsertedHTMLCallbacks || []).map(
|
|
140
|
+
(callback) => callback()
|
|
141
|
+
)
|
|
142
|
+
});
|
|
131
143
|
return ReactDomServer.renderToString(
|
|
132
|
-
import_react.default.createElement(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
144
|
+
(opts == null ? void 0 : opts.wrapper) ? import_react.default.createElement(
|
|
145
|
+
"div",
|
|
146
|
+
{ id: SERVER_INSERTED_HTML, hidden: true },
|
|
147
|
+
children
|
|
148
|
+
) : children
|
|
137
149
|
) || "";
|
|
138
150
|
};
|
|
139
151
|
function createMarkupGenerator(opts) {
|
|
@@ -142,10 +154,8 @@ function createMarkupGenerator(opts) {
|
|
|
142
154
|
const jsx = await jsxGeneratorDeferrer(url);
|
|
143
155
|
if (jsx) {
|
|
144
156
|
return new Promise(async (resolve, reject) => {
|
|
145
|
-
const serverInsertedHTMLCallbacks =
|
|
146
|
-
|
|
147
|
-
opts.ServerInsertedHTMLContext.Provider,
|
|
148
|
-
serverInsertedHTMLCallbacks
|
|
157
|
+
const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
|
|
158
|
+
opts.ServerInsertedHTMLContext.Provider
|
|
149
159
|
);
|
|
150
160
|
let chunks = [];
|
|
151
161
|
const writable = new import_stream.Writable();
|
|
@@ -155,7 +165,10 @@ function createMarkupGenerator(opts) {
|
|
|
155
165
|
};
|
|
156
166
|
writable.on("finish", async () => {
|
|
157
167
|
let html = Buffer.concat(chunks).toString("utf8");
|
|
158
|
-
|
|
168
|
+
const serverHTML = getGenerateStaticHTML(serverInsertedHTMLCallbacks);
|
|
169
|
+
if (serverHTML) {
|
|
170
|
+
html = html.replace(/<\/head>/, `${serverHTML}</head>`);
|
|
171
|
+
}
|
|
159
172
|
if (opts.helmetContext) {
|
|
160
173
|
html = html.replace(
|
|
161
174
|
/(<\/head>)/,
|
|
@@ -187,8 +200,136 @@ function createMarkupGenerator(opts) {
|
|
|
187
200
|
}
|
|
188
201
|
function createRequestHandler(opts) {
|
|
189
202
|
const jsxGeneratorDeferrer = createJSXGenerator(opts);
|
|
190
|
-
|
|
191
|
-
|
|
203
|
+
const normalizeHandlerArgs = (...args) => {
|
|
204
|
+
var _a, _b;
|
|
205
|
+
let ret;
|
|
206
|
+
const replaceServerHTMLScript = `<script>!function(){var e=document.getElementById("${SERVER_INSERTED_HTML}");e&&(Array.from(e.children).forEach(e=>{document.head.appendChild(e)}),e.remove())}();</script>`;
|
|
207
|
+
if (typeof FetchEvent !== "undefined" && args[0] instanceof FetchEvent) {
|
|
208
|
+
const [ev, workerOpts] = args;
|
|
209
|
+
const { pathname, searchParams } = new URL(ev.request.url);
|
|
210
|
+
ret = {
|
|
211
|
+
req: {
|
|
212
|
+
url: ev.request.url,
|
|
213
|
+
pathname,
|
|
214
|
+
headers: ev.request.headers,
|
|
215
|
+
query: {
|
|
216
|
+
route: searchParams.get("route"),
|
|
217
|
+
url: searchParams.get("url")
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
async sendServerLoader(data) {
|
|
221
|
+
let res = new Response(JSON.stringify(data), {
|
|
222
|
+
headers: {
|
|
223
|
+
"content-type": "application/json; charset=utf-8"
|
|
224
|
+
},
|
|
225
|
+
status: 200
|
|
226
|
+
});
|
|
227
|
+
if (workerOpts == null ? void 0 : workerOpts.modifyResponse) {
|
|
228
|
+
res = await workerOpts.modifyResponse(res);
|
|
229
|
+
}
|
|
230
|
+
ev.respondWith(res);
|
|
231
|
+
},
|
|
232
|
+
async sendPage(jsx) {
|
|
233
|
+
const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
|
|
234
|
+
opts.ServerInsertedHTMLContext.Provider
|
|
235
|
+
);
|
|
236
|
+
const stream = await ReactDomServer.renderToReadableStream(
|
|
237
|
+
import_react.default.createElement(JSXProvider, void 0, jsx.element),
|
|
238
|
+
{
|
|
239
|
+
bootstrapScripts: [jsx.manifest.assets["umi.js"] || "/umi.js"],
|
|
240
|
+
onError(x) {
|
|
241
|
+
console.error(x);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
const transformStream = new TransformStream({
|
|
246
|
+
flush(controller) {
|
|
247
|
+
if (serverInsertedHTMLCallbacks.size) {
|
|
248
|
+
const serverHTML = getGenerateStaticHTML(
|
|
249
|
+
serverInsertedHTMLCallbacks,
|
|
250
|
+
{ wrapper: true }
|
|
251
|
+
);
|
|
252
|
+
controller.enqueue(serverHTML);
|
|
253
|
+
controller.enqueue(replaceServerHTMLScript);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
stream.pipeThrough(transformStream);
|
|
258
|
+
let res = new Response(stream, {
|
|
259
|
+
headers: {
|
|
260
|
+
"content-type": "text/html; charset=utf-8"
|
|
261
|
+
},
|
|
262
|
+
status: 200
|
|
263
|
+
});
|
|
264
|
+
if (workerOpts == null ? void 0 : workerOpts.modifyResponse) {
|
|
265
|
+
res = await workerOpts.modifyResponse(res);
|
|
266
|
+
}
|
|
267
|
+
ev.respondWith(res);
|
|
268
|
+
},
|
|
269
|
+
otherwise() {
|
|
270
|
+
throw new Error("no page resource");
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
} else {
|
|
274
|
+
const [req, res, next] = args;
|
|
275
|
+
ret = {
|
|
276
|
+
req: {
|
|
277
|
+
url: `${req.protocol}://${req.get("host")}${req.originalUrl}`,
|
|
278
|
+
pathname: req.url,
|
|
279
|
+
headers: req.headers,
|
|
280
|
+
query: {
|
|
281
|
+
route: (_a = req.query.route) == null ? void 0 : _a.toString(),
|
|
282
|
+
url: (_b = req.query.url) == null ? void 0 : _b.toString()
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
sendServerLoader(data) {
|
|
286
|
+
res.status(200).json(data);
|
|
287
|
+
},
|
|
288
|
+
async sendPage(jsx) {
|
|
289
|
+
const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
|
|
290
|
+
opts.ServerInsertedHTMLContext.Provider
|
|
291
|
+
);
|
|
292
|
+
const writable = new import_stream.Writable();
|
|
293
|
+
res.type("html");
|
|
294
|
+
writable._write = (chunk, _encoding, cb) => {
|
|
295
|
+
res.write(chunk);
|
|
296
|
+
cb();
|
|
297
|
+
};
|
|
298
|
+
writable.on("finish", async () => {
|
|
299
|
+
if (serverInsertedHTMLCallbacks.size) {
|
|
300
|
+
res.write(
|
|
301
|
+
getGenerateStaticHTML(serverInsertedHTMLCallbacks, {
|
|
302
|
+
wrapper: true
|
|
303
|
+
})
|
|
304
|
+
);
|
|
305
|
+
res.write(replaceServerHTMLScript);
|
|
306
|
+
}
|
|
307
|
+
res.end();
|
|
308
|
+
});
|
|
309
|
+
const stream = ReactDomServer.renderToPipeableStream(
|
|
310
|
+
import_react.default.createElement(JSXProvider, void 0, jsx.element),
|
|
311
|
+
{
|
|
312
|
+
bootstrapScripts: [jsx.manifest.assets["umi.js"] || "/umi.js"],
|
|
313
|
+
onShellReady() {
|
|
314
|
+
stream.pipe(writable);
|
|
315
|
+
},
|
|
316
|
+
onError(x) {
|
|
317
|
+
console.error(x);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
);
|
|
321
|
+
},
|
|
322
|
+
otherwise: next
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
return ret;
|
|
326
|
+
};
|
|
327
|
+
return async function unifiedRequestHandler(...args) {
|
|
328
|
+
let jsx;
|
|
329
|
+
const { req, sendServerLoader, sendPage, otherwise } = normalizeHandlerArgs(
|
|
330
|
+
...args
|
|
331
|
+
);
|
|
332
|
+
if (req.pathname.startsWith("/__serverLoader") && req.query.route && req.query.url) {
|
|
192
333
|
const serverLoaderRequest = new Request(req.query.url, {
|
|
193
334
|
headers: req.headers
|
|
194
335
|
});
|
|
@@ -197,38 +338,27 @@ function createRequestHandler(opts) {
|
|
|
197
338
|
routesWithServerLoader: opts.routesWithServerLoader,
|
|
198
339
|
serverLoaderArgs: { request: serverLoaderRequest }
|
|
199
340
|
});
|
|
200
|
-
|
|
201
|
-
|
|
341
|
+
await sendServerLoader(data);
|
|
342
|
+
} else if (jsx = await jsxGeneratorDeferrer(req.pathname, {
|
|
343
|
+
request: new Request(req.url, {
|
|
344
|
+
headers: req.headers
|
|
345
|
+
})
|
|
346
|
+
})) {
|
|
347
|
+
await sendPage(jsx);
|
|
348
|
+
} else {
|
|
349
|
+
await otherwise();
|
|
202
350
|
}
|
|
203
|
-
const fullUrl = `${req.protocol}://${req.get("host")}${req.originalUrl}`;
|
|
204
|
-
const request = new Request(fullUrl, {
|
|
205
|
-
headers: req.headers
|
|
206
|
-
});
|
|
207
|
-
const jsx = await jsxGeneratorDeferrer(req.url, { request });
|
|
208
|
-
if (!jsx)
|
|
209
|
-
return next();
|
|
210
|
-
const writable = new import_stream.Writable();
|
|
211
|
-
writable._write = (chunk, _encoding, next2) => {
|
|
212
|
-
res.write(chunk);
|
|
213
|
-
next2();
|
|
214
|
-
};
|
|
215
|
-
writable.on("finish", async () => {
|
|
216
|
-
res.write(await getGenerateStaticHTML());
|
|
217
|
-
res.end();
|
|
218
|
-
});
|
|
219
|
-
const stream = await ReactDomServer.renderToPipeableStream(jsx.element, {
|
|
220
|
-
bootstrapScripts: [jsx.manifest.assets["umi.js"] || "/umi.js"],
|
|
221
|
-
onShellReady() {
|
|
222
|
-
stream.pipe(writable);
|
|
223
|
-
},
|
|
224
|
-
onError(x) {
|
|
225
|
-
console.error(x);
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
351
|
};
|
|
229
352
|
}
|
|
230
353
|
function createUmiHandler(opts) {
|
|
354
|
+
let isWarned = false;
|
|
231
355
|
return async function(req, params) {
|
|
356
|
+
if (!isWarned) {
|
|
357
|
+
console.warn(
|
|
358
|
+
"[umi] `renderRoot` is deprecated, please use `requestHandler` instead"
|
|
359
|
+
);
|
|
360
|
+
isWarned = true;
|
|
361
|
+
}
|
|
232
362
|
const jsxGeneratorDeferrer = createJSXGenerator({
|
|
233
363
|
...opts,
|
|
234
364
|
...params
|
|
@@ -247,7 +377,14 @@ function createUmiHandler(opts) {
|
|
|
247
377
|
};
|
|
248
378
|
}
|
|
249
379
|
function createUmiServerLoader(opts) {
|
|
380
|
+
let isWarned = false;
|
|
250
381
|
return async function(req) {
|
|
382
|
+
if (!isWarned) {
|
|
383
|
+
console.warn(
|
|
384
|
+
"[umi] `serverLoader` is deprecated, please use `requestHandler` instead"
|
|
385
|
+
);
|
|
386
|
+
isWarned = true;
|
|
387
|
+
}
|
|
251
388
|
const query = Object.fromEntries(new URL(req.url).searchParams);
|
|
252
389
|
const serverLoaderRequest = new Request(query.url, {
|
|
253
390
|
headers: req.headers
|
|
@@ -296,19 +433,21 @@ async function executeLoader(params) {
|
|
|
296
433
|
return mod.serverLoader(serverLoaderArgs);
|
|
297
434
|
}
|
|
298
435
|
async function executeMetadataLoader(params) {
|
|
299
|
-
const {
|
|
300
|
-
routesWithServerLoader,
|
|
301
|
-
routeKey,
|
|
302
|
-
serverLoaderArgs,
|
|
303
|
-
serverLoaderData
|
|
304
|
-
} = params;
|
|
436
|
+
const { routesWithServerLoader, routeKey, serverLoaderData } = params;
|
|
305
437
|
const mod = await routesWithServerLoader[routeKey]();
|
|
306
438
|
if (!mod.serverLoader || typeof mod.serverLoader !== "function") {
|
|
307
439
|
return;
|
|
308
440
|
}
|
|
309
|
-
|
|
310
|
-
serverLoaderData
|
|
311
|
-
|
|
441
|
+
const result = mod.metadataLoader(
|
|
442
|
+
serverLoaderData
|
|
443
|
+
);
|
|
444
|
+
return ["title", "description", "keywords", "lang", "metas"].reduce(
|
|
445
|
+
(acc, key) => {
|
|
446
|
+
if (Object.prototype.hasOwnProperty.call(result, key))
|
|
447
|
+
acc[key] = result[key];
|
|
448
|
+
return acc;
|
|
449
|
+
},
|
|
450
|
+
{}
|
|
312
451
|
);
|
|
313
452
|
}
|
|
314
453
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
export interface IOpts {
|
|
2
|
+
base: string;
|
|
3
|
+
routes: Record<string, {
|
|
4
|
+
path: string;
|
|
5
|
+
file: string;
|
|
6
|
+
id: string;
|
|
7
|
+
parentId?: string;
|
|
8
|
+
}>;
|
|
9
|
+
links?: Record<string, string>[];
|
|
10
|
+
metas?: Record<string, string>[];
|
|
11
|
+
styles?: (Record<string, string> | string)[];
|
|
12
|
+
favicons?: string[];
|
|
13
|
+
title?: string;
|
|
14
|
+
headScripts?: (Record<string, string> | string)[];
|
|
15
|
+
scripts?: (Record<string, string> | string)[];
|
|
16
|
+
mountElementId?: string;
|
|
17
|
+
esmScript?: boolean;
|
|
18
|
+
modifyHTML?: (html: string, args: {
|
|
19
|
+
path?: string;
|
|
20
|
+
}) => Promise<string>;
|
|
21
|
+
historyType?: 'hash' | 'browser';
|
|
22
|
+
}
|
|
23
|
+
export declare type IUserExtraRoute = string | {
|
|
24
|
+
path: string;
|
|
25
|
+
prerender: boolean;
|
|
26
|
+
};
|
|
1
27
|
export interface IRoute {
|
|
2
28
|
id: string;
|
|
3
29
|
path?: string;
|
|
@@ -29,6 +55,24 @@ export interface IMetadata {
|
|
|
29
55
|
*/
|
|
30
56
|
lang?: string;
|
|
31
57
|
metas?: IMetaTag[];
|
|
58
|
+
headScripts?: (Record<string, string> | string)[];
|
|
59
|
+
links?: Record<string, string>[];
|
|
60
|
+
styles?: string[];
|
|
61
|
+
favicons?: string[];
|
|
62
|
+
scripts?: (Record<string, string> | string)[];
|
|
63
|
+
[key: string]: any;
|
|
64
|
+
}
|
|
65
|
+
export interface ITplOpts {
|
|
66
|
+
title?: string;
|
|
67
|
+
description?: string;
|
|
68
|
+
keywords?: string[];
|
|
69
|
+
metas?: IMetaTag[];
|
|
70
|
+
headScripts?: (Record<string, string> | string)[];
|
|
71
|
+
links?: Record<string, string>[];
|
|
72
|
+
styles?: string[];
|
|
73
|
+
favicons?: string[];
|
|
74
|
+
scripts?: (Record<string, string> | string)[];
|
|
75
|
+
[key: string]: any;
|
|
32
76
|
}
|
|
33
77
|
export declare type MetadataLoader<T = any> = (serverLoaderData: T, req?: IServerLoaderArgs) => LoaderReturn<IMetadata>;
|
|
34
78
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umijs/server",
|
|
3
|
-
"version": "4.0.0-canary.
|
|
3
|
+
"version": "4.0.0-canary.20240402.1",
|
|
4
4
|
"description": "@umijs/server",
|
|
5
5
|
"homepage": "https://github.com/umijs/umi/tree/master/packages/server#readme",
|
|
6
6
|
"bugs": "https://github.com/umijs/umi/issues",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"react": "18.1.0",
|
|
20
20
|
"react-dom": "18.1.0",
|
|
21
21
|
"react-router-dom": "6.3.0",
|
|
22
|
-
"@umijs/bundler-utils": "4.0.0-canary.
|
|
22
|
+
"@umijs/bundler-utils": "4.0.0-canary.20240402.1"
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|
|
25
25
|
"access": "public"
|