@umijs/server 4.0.0-canary.20240509.4 → 4.0.0-canary.20240511.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 CHANGED
@@ -1,7 +1,5 @@
1
- /// <reference lib="webworker" />
2
- import type { RequestHandler } from '@umijs/bundler-utils/compiled/express';
3
1
  import React from 'react';
4
- import type { IhtmlPageOpts, UmiRequest } from './types';
2
+ import type { UmiRequest } from './types';
5
3
  interface RouteLoaders {
6
4
  [key: string]: () => Promise<any>;
7
5
  }
@@ -14,31 +12,22 @@ interface CreateRequestServerlessOptions {
14
12
  }
15
13
  interface CreateRequestHandlerOptions extends CreateRequestServerlessOptions {
16
14
  routesWithServerLoader: RouteLoaders;
17
- pluginManager: any;
15
+ PluginManager: any;
18
16
  manifest: ((sourceDir?: string) => {
19
17
  assets: Record<string, string>;
20
18
  }) | {
21
19
  assets: Record<string, string>;
22
20
  };
21
+ getPlugins: () => any;
22
+ getValidKeys: () => any;
23
23
  getRoutes: (PluginManager: any) => any;
24
24
  getClientRootComponent: (PluginManager: any) => any;
25
25
  createHistory: (opts: any) => any;
26
26
  helmetContext?: any;
27
27
  ServerInsertedHTMLContext: React.Context<ServerInsertedHTMLHook | null>;
28
- htmlPageOpts: IhtmlPageOpts;
29
- renderFromRoot: boolean;
30
- mountElementId: string;
31
28
  }
32
29
  export declare function createMarkupGenerator(opts: CreateRequestHandlerOptions): (url: string) => Promise<unknown>;
33
- declare type IExpressRequestHandlerArgs = Parameters<RequestHandler>;
34
- declare type IWorkerRequestHandlerArgs = [
35
- ev: FetchEvent,
36
- opts?: {
37
- modifyResponse?: (res: Response) => Promise<Response> | Response;
38
- }
39
- ];
40
- export default function createRequestHandler(opts: CreateRequestHandlerOptions): (...args: IExpressRequestHandlerArgs | IWorkerRequestHandlerArgs) => Promise<void>;
30
+ export default function createRequestHandler(opts: CreateRequestHandlerOptions): (req: any, res: any, next: any) => Promise<any>;
41
31
  export declare function createUmiHandler(opts: CreateRequestHandlerOptions): (req: UmiRequest, params?: CreateRequestHandlerOptions) => Promise<NodeJS.ReadableStream>;
42
32
  export declare function createUmiServerLoader(opts: CreateRequestHandlerOptions): (req: UmiRequest) => Promise<any>;
43
- export declare function createAppRootElement(opts: CreateRequestHandlerOptions): (...args: IExpressRequestHandlerArgs | IWorkerRequestHandlerArgs) => Promise<() => React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined>;
44
33
  export {};
package/dist/ssr.js CHANGED
@@ -29,7 +29,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/ssr.ts
30
30
  var ssr_exports = {};
31
31
  __export(ssr_exports, {
32
- createAppRootElement: () => createAppRootElement,
33
32
  createMarkupGenerator: () => createMarkupGenerator,
34
33
  createUmiHandler: () => createUmiHandler,
35
34
  createUmiServerLoader: () => createUmiServerLoader,
@@ -40,16 +39,7 @@ var import_react = __toESM(require("react"));
40
39
  var ReactDomServer = __toESM(require("react-dom/server"));
41
40
  var import_react_router_dom = require("react-router-dom");
42
41
  var import_stream = require("stream");
43
- var MetaLoaderResultKeys = /* @__PURE__ */ ((MetaLoaderResultKeys2) => {
44
- MetaLoaderResultKeys2["Title"] = "title";
45
- MetaLoaderResultKeys2["Description"] = "description";
46
- MetaLoaderResultKeys2["Keywords"] = "keywords";
47
- MetaLoaderResultKeys2["Lang"] = "lang";
48
- MetaLoaderResultKeys2["Metas"] = "metas";
49
- return MetaLoaderResultKeys2;
50
- })(MetaLoaderResultKeys || {});
51
- var createJSXProvider = (Provider) => {
52
- const serverInsertedHTMLCallbacks = /* @__PURE__ */ new Set();
42
+ var createJSXProvider = (Provider, serverInsertedHTMLCallbacks) => {
53
43
  const JSXProvider = (props) => {
54
44
  const addInsertedHtml = import_react.default.useCallback(
55
45
  (handler) => {
@@ -62,20 +52,26 @@ var createJSXProvider = (Provider) => {
62
52
  value: addInsertedHtml
63
53
  });
64
54
  };
65
- return [JSXProvider, serverInsertedHTMLCallbacks];
55
+ return JSXProvider;
66
56
  };
67
57
  function createJSXGenerator(opts) {
68
58
  return async (url, serverLoaderArgs) => {
69
59
  const {
70
60
  routesWithServerLoader,
71
- pluginManager,
61
+ PluginManager,
62
+ getPlugins,
63
+ getValidKeys,
72
64
  getRoutes,
73
65
  createHistory,
74
66
  sourceDir
75
67
  } = opts;
76
68
  createHistory({ type: "memory", initialEntries: [url], initialIndex: 1 });
69
+ const pluginManager = PluginManager.create({
70
+ plugins: getPlugins(),
71
+ validKeys: getValidKeys()
72
+ });
77
73
  const { routes, routeComponents } = await getRoutes(pluginManager);
78
- pluginManager.applyPlugins({
74
+ await pluginManager.applyPlugins({
79
75
  key: "patchRoutes",
80
76
  type: "event",
81
77
  args: {
@@ -88,6 +84,7 @@ function createJSXGenerator(opts) {
88
84
  return;
89
85
  }
90
86
  const loaderData = {};
87
+ const metadata = {};
91
88
  await Promise.all(
92
89
  matches.filter((id) => routes[id].hasServerLoader).map(
93
90
  (id) => new Promise(async (resolve) => {
@@ -97,19 +94,15 @@ function createJSXGenerator(opts) {
97
94
  serverLoaderArgs
98
95
  });
99
96
  if (routes[id].hasMetadataLoader) {
100
- const metadataLoaderData = await executeMetadataLoader({
101
- routesWithServerLoader,
102
- routeKey: id,
103
- serverLoaderArgs,
104
- serverLoaderData: loaderData[id]
105
- });
106
- metadataLoaderData && Object.entries(metadataLoaderData).forEach(([k, v]) => {
107
- if (Array.isArray(v)) {
108
- opts.htmlPageOpts[k] = (opts.htmlPageOpts[k] || []).concat(v);
109
- } else {
110
- opts.htmlPageOpts[k] = v;
111
- }
112
- });
97
+ Object.assign(
98
+ metadata,
99
+ await executeMetadataLoader({
100
+ routesWithServerLoader,
101
+ routeKey: id,
102
+ serverLoaderArgs,
103
+ serverLoaderData: loaderData[id]
104
+ })
105
+ );
113
106
  }
114
107
  resolve();
115
108
  })
@@ -123,9 +116,7 @@ function createJSXGenerator(opts) {
123
116
  location: url,
124
117
  manifest,
125
118
  loaderData,
126
- htmlPageOpts: opts.htmlPageOpts,
127
- renderFromRoot: opts.renderFromRoot,
128
- mountElementId: opts.mountElementId
119
+ metadata
129
120
  };
130
121
  const element = await opts.getClientRootComponent(
131
122
  context
@@ -136,19 +127,13 @@ function createJSXGenerator(opts) {
136
127
  };
137
128
  };
138
129
  }
139
- var SERVER_INSERTED_HTML = "umi-server-inserted-html";
140
- var getGenerateStaticHTML = (serverInsertedHTMLCallbacks, opts) => {
141
- const children = import_react.default.createElement(import_react.default.Fragment, {
142
- children: Array.from(serverInsertedHTMLCallbacks || []).map(
143
- (callback) => callback()
144
- )
145
- });
130
+ var getGenerateStaticHTML = (serverInsertedHTMLCallbacks) => {
146
131
  return ReactDomServer.renderToString(
147
- (opts == null ? void 0 : opts.wrapper) ? import_react.default.createElement(
148
- "div",
149
- { id: SERVER_INSERTED_HTML, hidden: true },
150
- children
151
- ) : children
132
+ import_react.default.createElement(import_react.default.Fragment, {
133
+ children: Array.from(serverInsertedHTMLCallbacks || []).map(
134
+ (callback) => callback()
135
+ )
136
+ })
152
137
  ) || "";
153
138
  };
154
139
  function createMarkupGenerator(opts) {
@@ -157,8 +142,10 @@ function createMarkupGenerator(opts) {
157
142
  const jsx = await jsxGeneratorDeferrer(url);
158
143
  if (jsx) {
159
144
  return new Promise(async (resolve, reject) => {
160
- const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
161
- opts.ServerInsertedHTMLContext.Provider
145
+ const serverInsertedHTMLCallbacks = /* @__PURE__ */ new Set();
146
+ const JSXProvider = createJSXProvider(
147
+ opts.ServerInsertedHTMLContext.Provider,
148
+ serverInsertedHTMLCallbacks
162
149
  );
163
150
  let chunks = [];
164
151
  const writable = new import_stream.Writable();
@@ -168,10 +155,7 @@ function createMarkupGenerator(opts) {
168
155
  };
169
156
  writable.on("finish", async () => {
170
157
  let html = Buffer.concat(chunks).toString("utf8");
171
- const serverHTML = getGenerateStaticHTML(serverInsertedHTMLCallbacks);
172
- if (serverHTML) {
173
- html = html.replace(/<\/head>/, `${serverHTML}</head>`);
174
- }
158
+ html += await getGenerateStaticHTML(serverInsertedHTMLCallbacks);
175
159
  if (opts.helmetContext) {
176
160
  html = html.replace(
177
161
  /(<\/head>)/,
@@ -193,7 +177,6 @@ function createMarkupGenerator(opts) {
193
177
  onShellReady() {
194
178
  stream.pipe(writable);
195
179
  },
196
- bootstrapScripts: [jsx.manifest.assets["umi.js"] || "/umi.js"],
197
180
  onError: reject
198
181
  }
199
182
  );
@@ -202,198 +185,50 @@ function createMarkupGenerator(opts) {
202
185
  return "";
203
186
  };
204
187
  }
205
- var normalizeRequest = (...args) => {
206
- var _a, _b;
207
- let request;
208
- let serverLoaderRequest;
209
- let serverLoaderArgs;
210
- if (process.env.SSR_BUILD_TARGET === "worker") {
211
- const [ev] = args;
212
- const { pathname, searchParams } = new URL(ev.request.url);
213
- request = {
214
- url: ev.request.url,
215
- pathname,
216
- headers: ev.request.headers,
217
- query: {
218
- route: searchParams.get("route"),
219
- url: searchParams.get("url")
220
- }
221
- };
222
- } else {
223
- const [req] = args;
224
- request = {
225
- url: `${req.protocol}://${req.get("host")}${req.originalUrl}`,
226
- pathname: req.url,
227
- headers: req.headers,
228
- query: {
229
- route: (_a = req.query.route) == null ? void 0 : _a.toString(),
230
- url: (_b = req.query.url) == null ? void 0 : _b.toString()
231
- }
232
- };
233
- }
234
- if (request.pathname.startsWith("/__serverLoader") && request.query.route && request.query.url) {
235
- serverLoaderRequest = new Request(request.query.url, {
236
- headers: request.headers
237
- });
238
- serverLoaderArgs = {
239
- request: serverLoaderRequest
240
- };
241
- }
242
- return {
243
- request,
244
- serverLoaderArgs
245
- };
246
- };
247
188
  function createRequestHandler(opts) {
248
189
  const jsxGeneratorDeferrer = createJSXGenerator(opts);
249
- const normalizeHandlerArgs = (...args) => {
250
- let ret;
251
- const { request } = normalizeRequest(...args);
252
- 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>`;
253
- if (process.env.SSR_BUILD_TARGET === "worker") {
254
- const [ev, workerOpts] = args;
255
- let asyncRespondWith;
256
- ev.respondWith(new Promise((r) => asyncRespondWith = r));
257
- ret = {
258
- req: request,
259
- async sendServerLoader(data) {
260
- let res = new Response(JSON.stringify(data), {
261
- headers: {
262
- "content-type": "application/json; charset=utf-8"
263
- },
264
- status: 200
265
- });
266
- if (workerOpts == null ? void 0 : workerOpts.modifyResponse) {
267
- res = await workerOpts.modifyResponse(res);
268
- }
269
- asyncRespondWith(res);
270
- },
271
- async sendPage(jsx) {
272
- const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
273
- opts.ServerInsertedHTMLContext.Provider
274
- );
275
- const stream = await ReactDomServer.renderToReadableStream(
276
- import_react.default.createElement(JSXProvider, void 0, jsx.element),
277
- {
278
- bootstrapScripts: [jsx.manifest.assets["umi.js"] || "/umi.js"],
279
- onError(x) {
280
- console.error(x);
281
- }
282
- }
283
- );
284
- const transformStream = new TransformStream({
285
- flush(controller) {
286
- if (serverInsertedHTMLCallbacks.size) {
287
- const serverHTML = getGenerateStaticHTML(
288
- serverInsertedHTMLCallbacks,
289
- { wrapper: true }
290
- );
291
- controller.enqueue(serverHTML);
292
- controller.enqueue(replaceServerHTMLScript);
293
- }
294
- }
295
- });
296
- let res = new Response(stream.pipeThrough(transformStream), {
297
- headers: {
298
- "content-type": "text/html; charset=utf-8"
299
- },
300
- status: 200
301
- });
302
- if (workerOpts == null ? void 0 : workerOpts.modifyResponse) {
303
- res = await workerOpts.modifyResponse(res);
304
- }
305
- asyncRespondWith(res);
306
- },
307
- otherwise() {
308
- throw new Error("no page resource");
309
- }
310
- };
311
- } else {
312
- const [_, res, next] = args;
313
- ret = {
314
- req: request,
315
- sendServerLoader(data) {
316
- res.status(200).json(data);
317
- },
318
- async sendPage(jsx) {
319
- const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
320
- opts.ServerInsertedHTMLContext.Provider
321
- );
322
- const writable = new import_stream.Writable();
323
- res.type("html");
324
- writable._write = (chunk, _encoding, cb) => {
325
- res.write(chunk);
326
- cb();
327
- };
328
- writable.on("finish", async () => {
329
- if (serverInsertedHTMLCallbacks.size) {
330
- res.write(
331
- getGenerateStaticHTML(serverInsertedHTMLCallbacks, {
332
- wrapper: true
333
- })
334
- );
335
- res.write(replaceServerHTMLScript);
336
- }
337
- res.end();
338
- });
339
- const stream = ReactDomServer.renderToPipeableStream(
340
- import_react.default.createElement(JSXProvider, void 0, jsx.element),
341
- {
342
- bootstrapScripts: [jsx.manifest.assets["umi.js"] || "/umi.js"],
343
- onShellReady() {
344
- stream.pipe(writable);
345
- },
346
- onError(x) {
347
- console.error(x);
348
- }
349
- }
350
- );
351
- },
352
- otherwise: next
353
- };
354
- }
355
- return ret;
356
- };
357
- return async function unifiedRequestHandler(...args) {
358
- const { req, sendServerLoader, sendPage, otherwise } = normalizeHandlerArgs(
359
- ...args
360
- );
361
- if (req.pathname.startsWith("/__serverLoader") && req.query.route && req.query.url) {
362
- const { serverLoaderArgs } = normalizeRequest(...args);
190
+ return async function(req, res, next) {
191
+ if (req.url.startsWith("/__serverLoader") && req.query.route) {
192
+ const serverLoaderRequest = new Request(req.query.url, {
193
+ headers: req.headers
194
+ });
363
195
  const data = await executeLoader({
364
196
  routeKey: req.query.route,
365
197
  routesWithServerLoader: opts.routesWithServerLoader,
366
- serverLoaderArgs
367
- });
368
- await sendServerLoader(data);
369
- } else {
370
- const render = opts.pluginManager.applyPlugins({
371
- key: "render",
372
- type: "compose",
373
- initialValue: () => jsxGeneratorDeferrer(req.pathname, {
374
- request: new Request(req.url, {
375
- headers: req.headers
376
- })
377
- })
198
+ serverLoaderArgs: { request: serverLoaderRequest }
378
199
  });
379
- const jsx = await render();
380
- if (jsx) {
381
- await sendPage(jsx);
382
- } else {
383
- await otherwise();
384
- }
200
+ res.status(200).json(data);
201
+ return;
385
202
  }
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
+ });
386
228
  };
387
229
  }
388
230
  function createUmiHandler(opts) {
389
- let isWarned = false;
390
231
  return async function(req, params) {
391
- if (!isWarned) {
392
- console.warn(
393
- "[umi] `renderRoot` is deprecated, please use `requestHandler` instead"
394
- );
395
- isWarned = true;
396
- }
397
232
  const jsxGeneratorDeferrer = createJSXGenerator({
398
233
  ...opts,
399
234
  ...params
@@ -412,14 +247,7 @@ function createUmiHandler(opts) {
412
247
  };
413
248
  }
414
249
  function createUmiServerLoader(opts) {
415
- let isWarned = false;
416
250
  return async function(req) {
417
- if (!isWarned) {
418
- console.warn(
419
- "[umi] `serverLoader` is deprecated, please use `requestHandler` instead"
420
- );
421
- isWarned = true;
422
- }
423
251
  const query = Object.fromEntries(new URL(req.url).searchParams);
424
252
  const serverLoaderRequest = new Request(query.url, {
425
253
  headers: req.headers
@@ -431,14 +259,6 @@ function createUmiServerLoader(opts) {
431
259
  });
432
260
  };
433
261
  }
434
- function createAppRootElement(opts) {
435
- return async (...args) => {
436
- const jsxGeneratorDeferrer = createJSXGenerator(opts);
437
- const { request, serverLoaderArgs } = normalizeRequest(...args);
438
- const jsx = await jsxGeneratorDeferrer(request.pathname, serverLoaderArgs);
439
- return () => jsx == null ? void 0 : jsx.element;
440
- };
441
- }
442
262
  function matchRoutesForSSR(reqUrl, routesById) {
443
263
  var _a;
444
264
  return ((_a = (0, import_react_router_dom.matchRoutes)(createClientRoutes({ routesById }), reqUrl)) == null ? void 0 : _a.map(
@@ -476,24 +296,23 @@ async function executeLoader(params) {
476
296
  return mod.serverLoader(serverLoaderArgs);
477
297
  }
478
298
  async function executeMetadataLoader(params) {
479
- const { routesWithServerLoader, routeKey, serverLoaderData } = params;
299
+ const {
300
+ routesWithServerLoader,
301
+ routeKey,
302
+ serverLoaderArgs,
303
+ serverLoaderData
304
+ } = params;
480
305
  const mod = await routesWithServerLoader[routeKey]();
481
306
  if (!mod.serverLoader || typeof mod.serverLoader !== "function") {
482
307
  return;
483
308
  }
484
- const loaderDatas = mod.metadataLoader(
485
- serverLoaderData
309
+ return mod.metadataLoader(
310
+ serverLoaderData,
311
+ serverLoaderArgs
486
312
  );
487
- const result = {};
488
- Object.values(MetaLoaderResultKeys).forEach((key) => {
489
- if (loaderDatas == null ? void 0 : loaderDatas[key])
490
- result[key] = loaderDatas[key];
491
- });
492
- return result;
493
313
  }
494
314
  // Annotate the CommonJS export names for ESM import in node:
495
315
  0 && (module.exports = {
496
- createAppRootElement,
497
316
  createMarkupGenerator,
498
317
  createUmiHandler,
499
318
  createUmiServerLoader
package/dist/types.d.ts CHANGED
@@ -1,29 +1,3 @@
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
- };
27
1
  export interface IRoute {
28
2
  id: string;
29
3
  path?: string;
@@ -56,13 +30,5 @@ export interface IMetadata {
56
30
  lang?: string;
57
31
  metas?: IMetaTag[];
58
32
  }
59
- export interface IhtmlPageOpts extends IMetadata {
60
- headScripts?: (Record<string, string> | string)[];
61
- links?: Record<string, string>[];
62
- styles?: string[];
63
- favicons?: string[];
64
- scripts?: (Record<string, string> | string)[];
65
- [key: string]: any;
66
- }
67
33
  export declare type MetadataLoader<T = any> = (serverLoaderData: T, req?: IServerLoaderArgs) => LoaderReturn<IMetadata>;
68
34
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umijs/server",
3
- "version": "4.0.0-canary.20240509.4",
3
+ "version": "4.0.0-canary.20240511.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.20240509.4"
22
+ "@umijs/bundler-utils": "4.0.0-canary.20240511.1"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"