@umijs/server 4.0.0-canary.20240514.3 → 4.0.0-canary.20240516.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,32 +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
- __SPECIAL_HTML_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: boolean;
31
- mountElementId: string;
32
28
  }
33
29
  export declare function createMarkupGenerator(opts: CreateRequestHandlerOptions): (url: string) => Promise<unknown>;
34
- declare type IExpressRequestHandlerArgs = Parameters<RequestHandler>;
35
- declare type IWorkerRequestHandlerArgs = [
36
- ev: FetchEvent,
37
- opts?: {
38
- modifyResponse?: (res: Response) => Promise<Response> | Response;
39
- }
40
- ];
41
- 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>;
42
31
  export declare function createUmiHandler(opts: CreateRequestHandlerOptions): (req: UmiRequest, params?: CreateRequestHandlerOptions) => Promise<NodeJS.ReadableStream>;
43
32
  export declare function createUmiServerLoader(opts: CreateRequestHandlerOptions): (req: UmiRequest) => Promise<any>;
44
- export declare function createAppRootElement(opts: CreateRequestHandlerOptions): (...args: IExpressRequestHandlerArgs | IWorkerRequestHandlerArgs) => Promise<() => React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined>;
45
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,10 +116,7 @@ function createJSXGenerator(opts) {
123
116
  location: url,
124
117
  manifest,
125
118
  loaderData,
126
- htmlPageOpts: opts.htmlPageOpts,
127
- renderFromRoot: opts.renderFromRoot,
128
- __SPECIAL_HTML_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: opts.__SPECIAL_HTML_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
129
- mountElementId: opts.mountElementId
119
+ metadata
130
120
  };
131
121
  const element = await opts.getClientRootComponent(
132
122
  context
@@ -137,19 +127,13 @@ function createJSXGenerator(opts) {
137
127
  };
138
128
  };
139
129
  }
140
- var SERVER_INSERTED_HTML = "umi-server-inserted-html";
141
- var getGenerateStaticHTML = (serverInsertedHTMLCallbacks, opts) => {
142
- const children = import_react.default.createElement(import_react.default.Fragment, {
143
- children: Array.from(serverInsertedHTMLCallbacks || []).map(
144
- (callback) => callback()
145
- )
146
- });
130
+ var getGenerateStaticHTML = (serverInsertedHTMLCallbacks) => {
147
131
  return ReactDomServer.renderToString(
148
- (opts == null ? void 0 : opts.wrapper) ? import_react.default.createElement(
149
- "div",
150
- { id: SERVER_INSERTED_HTML, hidden: true },
151
- children
152
- ) : children
132
+ import_react.default.createElement(import_react.default.Fragment, {
133
+ children: Array.from(serverInsertedHTMLCallbacks || []).map(
134
+ (callback) => callback()
135
+ )
136
+ })
153
137
  ) || "";
154
138
  };
155
139
  function createMarkupGenerator(opts) {
@@ -158,8 +142,10 @@ function createMarkupGenerator(opts) {
158
142
  const jsx = await jsxGeneratorDeferrer(url);
159
143
  if (jsx) {
160
144
  return new Promise(async (resolve, reject) => {
161
- const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
162
- opts.ServerInsertedHTMLContext.Provider
145
+ const serverInsertedHTMLCallbacks = /* @__PURE__ */ new Set();
146
+ const JSXProvider = createJSXProvider(
147
+ opts.ServerInsertedHTMLContext.Provider,
148
+ serverInsertedHTMLCallbacks
163
149
  );
164
150
  let chunks = [];
165
151
  const writable = new import_stream.Writable();
@@ -169,10 +155,7 @@ function createMarkupGenerator(opts) {
169
155
  };
170
156
  writable.on("finish", async () => {
171
157
  let html = Buffer.concat(chunks).toString("utf8");
172
- const serverHTML = getGenerateStaticHTML(serverInsertedHTMLCallbacks);
173
- if (serverHTML) {
174
- html = html.replace(/<\/head>/, `${serverHTML}</head>`);
175
- }
158
+ html += await getGenerateStaticHTML(serverInsertedHTMLCallbacks);
176
159
  if (opts.helmetContext) {
177
160
  html = html.replace(
178
161
  /(<\/head>)/,
@@ -194,7 +177,6 @@ function createMarkupGenerator(opts) {
194
177
  onShellReady() {
195
178
  stream.pipe(writable);
196
179
  },
197
- bootstrapScripts: [jsx.manifest.assets["umi.js"] || "/umi.js"],
198
180
  onError: reject
199
181
  }
200
182
  );
@@ -203,200 +185,50 @@ function createMarkupGenerator(opts) {
203
185
  return "";
204
186
  };
205
187
  }
206
- var normalizeRequest = (...args) => {
207
- var _a, _b;
208
- let request;
209
- let serverLoaderRequest;
210
- let serverLoaderArgs;
211
- if (process.env.SSR_BUILD_TARGET === "worker") {
212
- const [ev] = args;
213
- const { pathname, searchParams } = new URL(ev.request.url);
214
- request = {
215
- url: ev.request.url,
216
- pathname,
217
- headers: ev.request.headers,
218
- query: {
219
- route: searchParams.get("route"),
220
- url: searchParams.get("url")
221
- }
222
- };
223
- } else {
224
- const [req] = args;
225
- request = {
226
- url: `${req.protocol}://${req.get("host")}${req.originalUrl}`,
227
- pathname: req.url,
228
- headers: req.headers,
229
- query: {
230
- route: (_a = req.query.route) == null ? void 0 : _a.toString(),
231
- url: (_b = req.query.url) == null ? void 0 : _b.toString()
232
- }
233
- };
234
- }
235
- if (request.pathname.startsWith("/__serverLoader") && request.query.route && request.query.url) {
236
- serverLoaderRequest = new Request(request.query.url, {
237
- headers: request.headers
238
- });
239
- serverLoaderArgs = {
240
- request: serverLoaderRequest
241
- };
242
- }
243
- return {
244
- request,
245
- serverLoaderArgs
246
- };
247
- };
248
188
  function createRequestHandler(opts) {
249
189
  const jsxGeneratorDeferrer = createJSXGenerator(opts);
250
- const normalizeHandlerArgs = (...args) => {
251
- let ret;
252
- const { request } = normalizeRequest(...args);
253
- 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>`;
254
- if (process.env.SSR_BUILD_TARGET === "worker") {
255
- const [ev, workerOpts] = args;
256
- let asyncRespondWith;
257
- ev.respondWith(new Promise((r) => asyncRespondWith = r));
258
- ret = {
259
- req: request,
260
- async sendServerLoader(data) {
261
- let res = new Response(JSON.stringify(data), {
262
- headers: {
263
- "content-type": "application/json; charset=utf-8"
264
- },
265
- status: 200
266
- });
267
- if (workerOpts == null ? void 0 : workerOpts.modifyResponse) {
268
- res = await workerOpts.modifyResponse(res);
269
- }
270
- asyncRespondWith(res);
271
- },
272
- async sendPage(jsx) {
273
- const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
274
- opts.ServerInsertedHTMLContext.Provider
275
- );
276
- const stream = await ReactDomServer.renderToReadableStream(
277
- import_react.default.createElement(JSXProvider, void 0, jsx.element),
278
- {
279
- // why not bootstrap umi.js
280
- // ER will auto inject
281
- // bootstrapScripts: [jsx.manifest.assets['umi.js'] || '/umi.js'],
282
- onError(x) {
283
- console.error(x);
284
- }
285
- }
286
- );
287
- const transformStream = new TransformStream({
288
- flush(controller) {
289
- if (serverInsertedHTMLCallbacks.size) {
290
- const serverHTML = getGenerateStaticHTML(
291
- serverInsertedHTMLCallbacks,
292
- { wrapper: true }
293
- );
294
- controller.enqueue(serverHTML);
295
- controller.enqueue(replaceServerHTMLScript);
296
- }
297
- }
298
- });
299
- let res = new Response(stream.pipeThrough(transformStream), {
300
- headers: {
301
- "content-type": "text/html; charset=utf-8"
302
- },
303
- status: 200
304
- });
305
- if (workerOpts == null ? void 0 : workerOpts.modifyResponse) {
306
- res = await workerOpts.modifyResponse(res);
307
- }
308
- asyncRespondWith(res);
309
- },
310
- otherwise() {
311
- throw new Error("no page resource");
312
- }
313
- };
314
- } else {
315
- const [_, res, next] = args;
316
- ret = {
317
- req: request,
318
- sendServerLoader(data) {
319
- res.status(200).json(data);
320
- },
321
- async sendPage(jsx) {
322
- const [JSXProvider, serverInsertedHTMLCallbacks] = createJSXProvider(
323
- opts.ServerInsertedHTMLContext.Provider
324
- );
325
- const writable = new import_stream.Writable();
326
- res.type("html");
327
- writable._write = (chunk, _encoding, cb) => {
328
- res.write(chunk);
329
- cb();
330
- };
331
- writable.on("finish", async () => {
332
- if (serverInsertedHTMLCallbacks.size) {
333
- res.write(
334
- getGenerateStaticHTML(serverInsertedHTMLCallbacks, {
335
- wrapper: true
336
- })
337
- );
338
- res.write(replaceServerHTMLScript);
339
- }
340
- res.end();
341
- });
342
- const stream = ReactDomServer.renderToPipeableStream(
343
- import_react.default.createElement(JSXProvider, void 0, jsx.element),
344
- {
345
- bootstrapScripts: [jsx.manifest.assets["umi.js"] || "/umi.js"],
346
- onShellReady() {
347
- stream.pipe(writable);
348
- },
349
- onError(x) {
350
- console.error(x);
351
- }
352
- }
353
- );
354
- },
355
- otherwise: next
356
- };
357
- }
358
- return ret;
359
- };
360
- return async function unifiedRequestHandler(...args) {
361
- const { req, sendServerLoader, sendPage, otherwise } = normalizeHandlerArgs(
362
- ...args
363
- );
364
- if (req.pathname.startsWith("/__serverLoader") && req.query.route && req.query.url) {
365
- 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
+ });
366
195
  const data = await executeLoader({
367
196
  routeKey: req.query.route,
368
197
  routesWithServerLoader: opts.routesWithServerLoader,
369
- serverLoaderArgs
370
- });
371
- await sendServerLoader(data);
372
- } else {
373
- const render = opts.pluginManager.applyPlugins({
374
- key: "render",
375
- type: "compose",
376
- initialValue: () => jsxGeneratorDeferrer(req.pathname, {
377
- request: new Request(req.url, {
378
- headers: req.headers
379
- })
380
- })
198
+ serverLoaderArgs: { request: serverLoaderRequest }
381
199
  });
382
- const jsx = await render();
383
- if (jsx) {
384
- await sendPage(jsx);
385
- } else {
386
- await otherwise();
387
- }
200
+ res.status(200).json(data);
201
+ return;
388
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
+ });
389
228
  };
390
229
  }
391
230
  function createUmiHandler(opts) {
392
- let isWarned = false;
393
231
  return async function(req, params) {
394
- if (!isWarned) {
395
- console.warn(
396
- "[umi] `renderRoot` is deprecated, please use `requestHandler` instead"
397
- );
398
- isWarned = true;
399
- }
400
232
  const jsxGeneratorDeferrer = createJSXGenerator({
401
233
  ...opts,
402
234
  ...params
@@ -415,14 +247,7 @@ function createUmiHandler(opts) {
415
247
  };
416
248
  }
417
249
  function createUmiServerLoader(opts) {
418
- let isWarned = false;
419
250
  return async function(req) {
420
- if (!isWarned) {
421
- console.warn(
422
- "[umi] `serverLoader` is deprecated, please use `requestHandler` instead"
423
- );
424
- isWarned = true;
425
- }
426
251
  const query = Object.fromEntries(new URL(req.url).searchParams);
427
252
  const serverLoaderRequest = new Request(query.url, {
428
253
  headers: req.headers
@@ -434,14 +259,6 @@ function createUmiServerLoader(opts) {
434
259
  });
435
260
  };
436
261
  }
437
- function createAppRootElement(opts) {
438
- return async (...args) => {
439
- const jsxGeneratorDeferrer = createJSXGenerator(opts);
440
- const { request, serverLoaderArgs } = normalizeRequest(...args);
441
- const jsx = await jsxGeneratorDeferrer(request.pathname, serverLoaderArgs);
442
- return () => jsx == null ? void 0 : jsx.element;
443
- };
444
- }
445
262
  function matchRoutesForSSR(reqUrl, routesById) {
446
263
  var _a;
447
264
  return ((_a = (0, import_react_router_dom.matchRoutes)(createClientRoutes({ routesById }), reqUrl)) == null ? void 0 : _a.map(
@@ -479,24 +296,23 @@ async function executeLoader(params) {
479
296
  return mod.serverLoader(serverLoaderArgs);
480
297
  }
481
298
  async function executeMetadataLoader(params) {
482
- const { routesWithServerLoader, routeKey, serverLoaderData } = params;
299
+ const {
300
+ routesWithServerLoader,
301
+ routeKey,
302
+ serverLoaderArgs,
303
+ serverLoaderData
304
+ } = params;
483
305
  const mod = await routesWithServerLoader[routeKey]();
484
306
  if (!mod.serverLoader || typeof mod.serverLoader !== "function") {
485
307
  return;
486
308
  }
487
- const loaderDatas = mod.metadataLoader(
488
- serverLoaderData
309
+ return mod.metadataLoader(
310
+ serverLoaderData,
311
+ serverLoaderArgs
489
312
  );
490
- const result = {};
491
- Object.values(MetaLoaderResultKeys).forEach((key) => {
492
- if (loaderDatas == null ? void 0 : loaderDatas[key])
493
- result[key] = loaderDatas[key];
494
- });
495
- return result;
496
313
  }
497
314
  // Annotate the CommonJS export names for ESM import in node:
498
315
  0 && (module.exports = {
499
- createAppRootElement,
500
316
  createMarkupGenerator,
501
317
  createUmiHandler,
502
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.20240514.3",
3
+ "version": "4.0.0-canary.20240516.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.20240514.3"
22
+ "@umijs/bundler-utils": "4.0.0-canary.20240516.1"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"