@modern-js/prod-server 1.0.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.
Files changed (173) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +30 -0
  4. package/dist/js/modern/constants.js +26 -0
  5. package/dist/js/modern/index.js +14 -0
  6. package/dist/js/modern/libs/context/context.js +180 -0
  7. package/dist/js/modern/libs/context/index.js +3 -0
  8. package/dist/js/modern/libs/hook-api/route.js +39 -0
  9. package/dist/js/modern/libs/hook-api/template.js +61 -0
  10. package/dist/js/modern/libs/metrics.js +12 -0
  11. package/dist/js/modern/libs/proxy.js +33 -0
  12. package/dist/js/modern/libs/render/cache/__tests__/cache.fun.test.js +70 -0
  13. package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +233 -0
  14. package/dist/js/modern/libs/render/cache/__tests__/cacheable.js +53 -0
  15. package/dist/js/modern/libs/render/cache/__tests__/error-configuration.js +35 -0
  16. package/dist/js/modern/libs/render/cache/__tests__/matched-cache.js +121 -0
  17. package/dist/js/modern/libs/render/cache/index.js +74 -0
  18. package/dist/js/modern/libs/render/cache/page-caches/index.js +9 -0
  19. package/dist/js/modern/libs/render/cache/page-caches/lru.js +35 -0
  20. package/dist/js/modern/libs/render/cache/spr.js +280 -0
  21. package/dist/js/modern/libs/render/cache/type.js +1 -0
  22. package/dist/js/modern/libs/render/cache/util.js +79 -0
  23. package/dist/js/modern/libs/render/index.js +65 -0
  24. package/dist/js/modern/libs/render/modern/browser-list.js +7 -0
  25. package/dist/js/modern/libs/render/modern/index.js +42 -0
  26. package/dist/js/modern/libs/render/reader.js +112 -0
  27. package/dist/js/modern/libs/render/ssr.js +58 -0
  28. package/dist/js/modern/libs/render/static.js +46 -0
  29. package/dist/js/modern/libs/render/type.js +7 -0
  30. package/dist/js/modern/libs/route/index.js +68 -0
  31. package/dist/js/modern/libs/route/matcher.js +94 -0
  32. package/dist/js/modern/libs/route/route.js +24 -0
  33. package/dist/js/modern/libs/serve-file.js +28 -0
  34. package/dist/js/modern/server/index.js +120 -0
  35. package/dist/js/modern/server/modern-server-split.js +81 -0
  36. package/dist/js/modern/server/modern-server.js +576 -0
  37. package/dist/js/modern/type.js +1 -0
  38. package/dist/js/modern/utils.js +112 -0
  39. package/dist/js/node/constants.js +36 -0
  40. package/dist/js/node/index.js +74 -0
  41. package/dist/js/node/libs/context/context.js +194 -0
  42. package/dist/js/node/libs/context/index.js +18 -0
  43. package/dist/js/node/libs/hook-api/route.js +48 -0
  44. package/dist/js/node/libs/hook-api/template.js +69 -0
  45. package/dist/js/node/libs/metrics.js +18 -0
  46. package/dist/js/node/libs/proxy.js +44 -0
  47. package/dist/js/node/libs/render/cache/__tests__/cache.fun.test.js +77 -0
  48. package/dist/js/node/libs/render/cache/__tests__/cache.test.js +238 -0
  49. package/dist/js/node/libs/render/cache/__tests__/cacheable.js +60 -0
  50. package/dist/js/node/libs/render/cache/__tests__/error-configuration.js +42 -0
  51. package/dist/js/node/libs/render/cache/__tests__/matched-cache.js +128 -0
  52. package/dist/js/node/libs/render/cache/index.js +86 -0
  53. package/dist/js/node/libs/render/cache/page-caches/index.js +17 -0
  54. package/dist/js/node/libs/render/cache/page-caches/lru.js +47 -0
  55. package/dist/js/node/libs/render/cache/spr.js +298 -0
  56. package/dist/js/node/libs/render/cache/type.js +5 -0
  57. package/dist/js/node/libs/render/cache/util.js +105 -0
  58. package/dist/js/node/libs/render/index.js +91 -0
  59. package/dist/js/node/libs/render/modern/browser-list.js +14 -0
  60. package/dist/js/node/libs/render/modern/index.js +58 -0
  61. package/dist/js/node/libs/render/reader.js +139 -0
  62. package/dist/js/node/libs/render/ssr.js +76 -0
  63. package/dist/js/node/libs/render/static.js +62 -0
  64. package/dist/js/node/libs/render/type.js +14 -0
  65. package/dist/js/node/libs/route/index.js +83 -0
  66. package/dist/js/node/libs/route/matcher.js +108 -0
  67. package/dist/js/node/libs/route/route.js +33 -0
  68. package/dist/js/node/libs/serve-file.js +41 -0
  69. package/dist/js/node/server/index.js +142 -0
  70. package/dist/js/node/server/modern-server-split.js +97 -0
  71. package/dist/js/node/server/modern-server.js +614 -0
  72. package/dist/js/node/type.js +5 -0
  73. package/dist/js/node/utils.js +143 -0
  74. package/dist/js/styles/tsconfig.json +12 -0
  75. package/dist/types/constants.d.ts +20 -0
  76. package/dist/types/index.d.ts +11 -0
  77. package/dist/types/libs/context/context.d.ts +61 -0
  78. package/dist/types/libs/context/index.d.ts +4 -0
  79. package/dist/types/libs/hook-api/route.d.ts +14 -0
  80. package/dist/types/libs/hook-api/template.d.ts +14 -0
  81. package/dist/types/libs/metrics.d.ts +3 -0
  82. package/dist/types/libs/proxy.d.ts +4 -0
  83. package/dist/types/libs/render/cache/__tests__/cache.fun.test.d.ts +1 -0
  84. package/dist/types/libs/render/cache/__tests__/cache.test.d.ts +1 -0
  85. package/dist/types/libs/render/cache/__tests__/cacheable.d.ts +62 -0
  86. package/dist/types/libs/render/cache/__tests__/error-configuration.d.ts +28 -0
  87. package/dist/types/libs/render/cache/__tests__/matched-cache.d.ts +124 -0
  88. package/dist/types/libs/render/cache/index.d.ts +6 -0
  89. package/dist/types/libs/render/cache/page-caches/index.d.ts +2 -0
  90. package/dist/types/libs/render/cache/page-caches/lru.d.ts +15 -0
  91. package/dist/types/libs/render/cache/spr.d.ts +24 -0
  92. package/dist/types/libs/render/cache/type.d.ts +48 -0
  93. package/dist/types/libs/render/cache/util.d.ts +17 -0
  94. package/dist/types/libs/render/index.d.ts +18 -0
  95. package/dist/types/libs/render/modern/browser-list.d.ts +1 -0
  96. package/dist/types/libs/render/modern/index.d.ts +3 -0
  97. package/dist/types/libs/render/reader.d.ts +18 -0
  98. package/dist/types/libs/render/ssr.d.ts +10 -0
  99. package/dist/types/libs/render/static.d.ts +3 -0
  100. package/dist/types/libs/render/type.d.ts +33 -0
  101. package/dist/types/libs/route/index.d.ts +15 -0
  102. package/dist/types/libs/route/matcher.d.ts +15 -0
  103. package/dist/types/libs/route/route.d.ts +14 -0
  104. package/dist/types/libs/serve-file.d.ts +8 -0
  105. package/dist/types/server/index.d.ts +20 -0
  106. package/dist/types/server/modern-server-split.d.ts +26 -0
  107. package/dist/types/server/modern-server.d.ts +72 -0
  108. package/dist/types/type.d.ts +56 -0
  109. package/dist/types/utils.d.ts +19 -0
  110. package/jest.config.js +9 -0
  111. package/modern.config.js +2 -0
  112. package/package.json +82 -0
  113. package/src/constants.ts +26 -0
  114. package/src/index.ts +18 -0
  115. package/src/libs/context/context.ts +183 -0
  116. package/src/libs/context/index.ts +7 -0
  117. package/src/libs/hook-api/route.ts +42 -0
  118. package/src/libs/hook-api/template.ts +53 -0
  119. package/src/libs/metrics.ts +15 -0
  120. package/src/libs/proxy.ts +42 -0
  121. package/src/libs/render/cache/__tests__/cache.fun.test.ts +94 -0
  122. package/src/libs/render/cache/__tests__/cache.test.ts +240 -0
  123. package/src/libs/render/cache/__tests__/cacheable.ts +44 -0
  124. package/src/libs/render/cache/__tests__/error-configuration.ts +34 -0
  125. package/src/libs/render/cache/__tests__/matched-cache.ts +88 -0
  126. package/src/libs/render/cache/index.ts +75 -0
  127. package/src/libs/render/cache/page-caches/index.ts +11 -0
  128. package/src/libs/render/cache/page-caches/lru.ts +38 -0
  129. package/src/libs/render/cache/spr.ts +301 -0
  130. package/src/libs/render/cache/type.ts +59 -0
  131. package/src/libs/render/cache/util.ts +97 -0
  132. package/src/libs/render/index.ts +79 -0
  133. package/src/libs/render/modern/browser-list.ts +7 -0
  134. package/src/libs/render/modern/index.ts +41 -0
  135. package/src/libs/render/modern/module.d.ts +4 -0
  136. package/src/libs/render/reader.ts +119 -0
  137. package/src/libs/render/ssr.ts +67 -0
  138. package/src/libs/render/static.ts +52 -0
  139. package/src/libs/render/type.ts +38 -0
  140. package/src/libs/route/index.ts +76 -0
  141. package/src/libs/route/matcher.ts +108 -0
  142. package/src/libs/route/route.ts +34 -0
  143. package/src/libs/serve-file.ts +34 -0
  144. package/src/server/index.ts +147 -0
  145. package/src/server/modern-server-split.ts +97 -0
  146. package/src/server/modern-server.ts +613 -0
  147. package/src/tsconfig.json +12 -0
  148. package/src/type.ts +61 -0
  149. package/src/utils.ts +122 -0
  150. package/tests/.eslintrc.js +6 -0
  151. package/tests/context.test.ts +52 -0
  152. package/tests/fixtures/hosting-files/static/index.js +1 -0
  153. package/tests/fixtures/pure/modern.config.js +5 -0
  154. package/tests/fixtures/pure/package.json +21 -0
  155. package/tests/fixtures/pure/src/App.css +119 -0
  156. package/tests/fixtures/pure/src/App.tsx +43 -0
  157. package/tests/fixtures/pure/tsconfig.json +12 -0
  158. package/tests/fixtures/reader/index.ts +3 -0
  159. package/tests/fixtures/route-spec/dynamic.json +13 -0
  160. package/tests/fixtures/route-spec/index.json +29 -0
  161. package/tests/fixtures/ssr/bundle.js +5 -0
  162. package/tests/fixtures/static-dir/bar.html +11 -0
  163. package/tests/fixtures/static-dir/baz/index.html +11 -0
  164. package/tests/fixtures/static-dir/foo/index.html +11 -0
  165. package/tests/helper.ts +8 -0
  166. package/tests/hook.test.ts +44 -0
  167. package/tests/middleware.test.ts +179 -0
  168. package/tests/render.test.ts +102 -0
  169. package/tests/route.test.ts +77 -0
  170. package/tests/server.test.ts +101 -0
  171. package/tests/tsconfig.json +12 -0
  172. package/tests/utils.test.ts +106 -0
  173. package/tsconfig.json +11 -0
@@ -0,0 +1,614 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ModernServer = void 0;
7
+
8
+ var _http = require("http");
9
+
10
+ var _util = _interopRequireDefault(require("util"));
11
+
12
+ var _path = _interopRequireDefault(require("path"));
13
+
14
+ var _utils = require("@modern-js/utils");
15
+
16
+ var _mimeTypes = _interopRequireDefault(require("mime-types"));
17
+
18
+ var _axios = _interopRequireDefault(require("axios"));
19
+
20
+ var _lodash = _interopRequireDefault(require("lodash.clone"));
21
+
22
+ var _route = require("../libs/route");
23
+
24
+ var _render = require("../libs/render");
25
+
26
+ var _serveFile = require("../libs/serve-file");
27
+
28
+ var _utils2 = require("../utils");
29
+
30
+ var reader = _interopRequireWildcard(require("../libs/render/reader"));
31
+
32
+ var _proxy = require("../libs/proxy");
33
+
34
+ var _context = require("../libs/context");
35
+
36
+ var _constants = require("../constants");
37
+
38
+ var _template = require("../libs/hook-api/template");
39
+
40
+ var _route2 = require("../libs/hook-api/route");
41
+
42
+ const _excluded = ["getMiddlewares"];
43
+
44
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
45
+
46
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
47
+
48
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
49
+
50
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
51
+
52
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
53
+
54
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
55
+
56
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
57
+
58
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
59
+
60
+ const API_DIR = './api';
61
+ const SERVER_DIR = './server';
62
+
63
+ class ModernServer {
64
+ // appDirectory
65
+ // product dist dir
66
+ // work on src or dist
67
+ constructor({
68
+ pwd,
69
+ config,
70
+ routes,
71
+ staticGenerate,
72
+ logger,
73
+ metrics,
74
+ proxyTarget
75
+ }) {
76
+ var _config$output;
77
+
78
+ this.pwd = void 0;
79
+ this.distDir = void 0;
80
+ this.workDir = void 0;
81
+ this.router = void 0;
82
+ this.conf = void 0;
83
+ this.handlers = [];
84
+ this.presetRoutes = void 0;
85
+ this.runner = void 0;
86
+ this.logger = void 0;
87
+ this.metrics = void 0;
88
+ this.reader = reader;
89
+ this.proxyTarget = void 0;
90
+ this.staticFileHandler = void 0;
91
+ this.routeRenderHandler = void 0;
92
+ this.frameWebHandler = null;
93
+ this.frameAPIHandler = null;
94
+ this.proxyHandler = null;
95
+ this._handler = void 0;
96
+ this.staticGenerate = false;
97
+
98
+ require('ignore-styles');
99
+
100
+ this.pwd = pwd;
101
+ this.distDir = _path.default.join(pwd, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist');
102
+ this.workDir = this.distDir;
103
+ this.conf = config;
104
+ this.logger = logger;
105
+ this.metrics = metrics;
106
+ this.router = new _route.RouteMatchManager();
107
+ this.presetRoutes = routes;
108
+ this.proxyTarget = proxyTarget;
109
+
110
+ if (staticGenerate) {
111
+ this.staticGenerate = staticGenerate;
112
+ }
113
+
114
+ process.env.BUILD_TYPE = `${this.staticGenerate ? 'ssg' : 'ssr'}`;
115
+ } // exposed requestHandler
116
+
117
+
118
+ getRequestHandler() {
119
+ return this.requestHandler.bind(this);
120
+ } // server prepare
121
+
122
+
123
+ async init(runner) {
124
+ var _conf$bff;
125
+
126
+ this.runner = runner;
127
+ const {
128
+ distDir,
129
+ staticGenerate,
130
+ conf
131
+ } = this;
132
+ this.addHandler((ctx, next) => {
133
+ ctx.res.setHeader('Access-Control-Allow-Origin', '*');
134
+ ctx.res.setHeader('Access-Control-Allow-Credentials', 'false');
135
+ next();
136
+ }); // proxy handler, each proxy has own handler
137
+
138
+ this.proxyHandler = (0, _proxy.createProxyHandler)((_conf$bff = conf.bff) === null || _conf$bff === void 0 ? void 0 : _conf$bff.proxy);
139
+
140
+ if (this.proxyHandler) {
141
+ this.proxyHandler.forEach(handler => {
142
+ this.addHandler(handler);
143
+ });
144
+ } // start reader, include an time interval
145
+
146
+
147
+ this.reader.init(); // use preset routes priority
148
+
149
+ this.router.reset(this.filterRoutes(this.presetRoutes || this.readRouteSpec()));
150
+ this.warmupSSRBundle();
151
+ await this.prepareFrameHandler(); // Only work when without setting `assetPrefix`.
152
+ // Setting `assetPrefix` means these resources should be uploaded to CDN.
153
+
154
+ const staticPathRegExp = (0, _utils2.getStaticReg)(this.conf.output || {});
155
+ this.staticFileHandler = (0, _serveFile.createStaticFileHandler)([{
156
+ path: staticPathRegExp,
157
+ target: distDir
158
+ }]);
159
+ this.routeRenderHandler = (0, _render.createRenderHandler)({
160
+ distDir,
161
+ staticGenerate
162
+ });
163
+ await this.preServerInit();
164
+ this.addHandler(this.staticFileHandler);
165
+ this.addHandler(this.routeHandler.bind(this));
166
+ this.compose();
167
+ } // server ready
168
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
169
+
170
+
171
+ ready(_) {} // invoke when http server listen
172
+
173
+
174
+ onListening(_) {// empty
175
+ } // close any thing run in server
176
+
177
+
178
+ async close() {
179
+ this.reader.close();
180
+ }
181
+
182
+ async createHTTPServer(handler) {
183
+ return (0, _http.createServer)(handler);
184
+ } // read route spec from route.json
185
+
186
+
187
+ readRouteSpec() {
188
+ const file = _path.default.join(this.distDir, _utils.ROUTE_SPEC_FILE);
189
+
190
+ if (_utils.fs.existsSync(file)) {
191
+ const content = _utils.fs.readJSONSync(file);
192
+
193
+ return content.routes;
194
+ }
195
+
196
+ return [];
197
+ } // add promisify request handler to server
198
+ // handler should do not do more things after invoke next
199
+
200
+
201
+ addHandler(handler) {
202
+ if (handler[Symbol.toStringTag] === 'AsyncFunction') {
203
+ this.handlers.push(handler);
204
+ } else {
205
+ this.handlers.push(_util.default.promisify(handler));
206
+ }
207
+ } // return 404 page
208
+
209
+
210
+ render404(context) {
211
+ context.error(_constants.ERROR_DIGEST.ENOTF);
212
+ this.renderErrorPage(context, 404);
213
+ } // gather frame extension and get framework handler
214
+
215
+
216
+ async prepareFrameHandler() {
217
+ const {
218
+ workDir,
219
+ runner
220
+ } = this; // server hook, gather plugin inject
221
+
222
+ const _createMiddlewareColl = (0, _utils2.createMiddlewareCollecter)(),
223
+ {
224
+ getMiddlewares
225
+ } = _createMiddlewareColl,
226
+ collector = _objectWithoutProperties(_createMiddlewareColl, _excluded);
227
+
228
+ await runner.gather(collector);
229
+ const {
230
+ api: pluginAPIExt,
231
+ web: pluginWebExt
232
+ } = getMiddlewares();
233
+
234
+ const apiDir = _path.default.join(workDir, API_DIR);
235
+
236
+ const serverDir = _path.default.join(workDir, SERVER_DIR); // get api or web server handler from server-framework plugin
237
+
238
+
239
+ if (await _utils.fs.pathExists(_path.default.join(serverDir))) {
240
+ const webExtension = (0, _utils2.mergeExtension)(pluginWebExt);
241
+ this.frameWebHandler = await this.prepareWebHandler(webExtension);
242
+ }
243
+
244
+ if (_utils.fs.existsSync(apiDir)) {
245
+ const mode = _utils.fs.existsSync(_path.default.join(apiDir, _constants.AGGRED_DIR.lambda)) ? _constants.ApiServerMode.frame : _constants.ApiServerMode.func; // if use lambda/, mean framework style of writing, then discard user extension
246
+
247
+ const apiExtension = (0, _utils2.mergeExtension)(pluginAPIExt);
248
+ this.frameAPIHandler = await this.prepareAPIHandler(mode, apiExtension);
249
+ }
250
+ } // Todo
251
+
252
+
253
+ async proxy() {
254
+ return null;
255
+ }
256
+ /* —————————————————————— function will be overwrite —————————————————————— */
257
+
258
+
259
+ async prepareWebHandler(extension) {
260
+ const {
261
+ workDir,
262
+ runner
263
+ } = this;
264
+ return runner.prepareWebServer({
265
+ pwd: workDir,
266
+ config: extension
267
+ }, {
268
+ onLast: () => null
269
+ });
270
+ }
271
+
272
+ async prepareAPIHandler(mode, extension) {
273
+ const {
274
+ workDir,
275
+ runner,
276
+ conf
277
+ } = this;
278
+ const {
279
+ bff
280
+ } = conf;
281
+ const prefix = (bff === null || bff === void 0 ? void 0 : bff.prefix) || '/api';
282
+ return runner.prepareApiServer({
283
+ pwd: workDir,
284
+ mode,
285
+ config: extension,
286
+ prefix: Array.isArray(prefix) ? prefix[0] : prefix
287
+ }, {
288
+ onLast: () => null
289
+ });
290
+ }
291
+
292
+ filterRoutes(routes) {
293
+ return routes;
294
+ }
295
+
296
+ async emitRouteHook(eventName, input) {
297
+ input.context = (0, _lodash.default)(input.context);
298
+ return this.runner[eventName](input, {
299
+ onLast: _utils2.noop
300
+ });
301
+ } // warmup ssr function
302
+
303
+
304
+ warmupSSRBundle() {
305
+ const {
306
+ distDir
307
+ } = this;
308
+ const bundles = this.router.getBundles();
309
+ bundles.forEach(bundle => {
310
+ const filepath = _path.default.join(distDir, bundle); // if error, just throw and let process die
311
+
312
+
313
+ require(filepath);
314
+ });
315
+ }
316
+
317
+ async preServerInit() {
318
+ const {
319
+ conf,
320
+ runner
321
+ } = this;
322
+ const preMiddleware = await runner.preServerInit(conf);
323
+ preMiddleware.flat().forEach(mid => {
324
+ this.addHandler(mid);
325
+ });
326
+ }
327
+
328
+ async handleAPI(context) {
329
+ const {
330
+ req,
331
+ res
332
+ } = context;
333
+
334
+ if (!this.frameAPIHandler) {
335
+ throw new Error('can not found api hanlder');
336
+ }
337
+
338
+ await this.frameAPIHandler(req, res);
339
+ }
340
+
341
+ async handleWeb(context, route) {
342
+ return this.routeRenderHandler({
343
+ ctx: context,
344
+ route,
345
+ runner: this.runner
346
+ });
347
+ }
348
+
349
+ verifyMatch(_c, _m) {// empty
350
+ }
351
+ /* —————————————————————— private function —————————————————————— */
352
+ // handler route.json, include api / csr / ssr
353
+ // eslint-disable-next-line max-statements
354
+
355
+
356
+ async routeHandler(context) {
357
+ const {
358
+ req,
359
+ res
360
+ } = context;
361
+ await this.emitRouteHook('beforeMatch', {
362
+ context
363
+ }); // match routes in the route spec
364
+
365
+ const matched = this.router.match(context.path);
366
+
367
+ if (!matched) {
368
+ this.render404(context);
369
+ return;
370
+ } else {
371
+ this.verifyMatch(context, matched);
372
+ }
373
+
374
+ if (res.headersSent) {
375
+ return;
376
+ }
377
+
378
+ const routeAPI = (0, _route2.createRouteAPI)(matched, this.router, context.url);
379
+ await this.emitRouteHook('afterMatch', {
380
+ context,
381
+ routeAPI
382
+ });
383
+
384
+ if (res.headersSent) {
385
+ return;
386
+ }
387
+
388
+ const {
389
+ current
390
+ } = routeAPI;
391
+ const route = current.generate(context.url);
392
+ context.setParams(route.params);
393
+ context.setServerData('router', {
394
+ baseUrl: route.urlPath,
395
+ params: route.params
396
+ }); // route is api service
397
+
398
+ if (route.isApi) {
399
+ await this.handleAPI(context);
400
+ return;
401
+ }
402
+
403
+ if (this.frameWebHandler) {
404
+ await this.frameWebHandler(req, res);
405
+ } // frameWebHandler has process request
406
+
407
+
408
+ if (res.headersSent) {
409
+ return;
410
+ }
411
+
412
+ if (route.entryName) {
413
+ await this.emitRouteHook('beforeRender', {
414
+ context
415
+ });
416
+ }
417
+
418
+ const file = await this.handleWeb(context, route);
419
+
420
+ if (!file) {
421
+ this.render404(context);
422
+ return;
423
+ }
424
+
425
+ if (file.redirect) {
426
+ res.statusCode = file.statusCode;
427
+ res.setHeader('Location', file.content);
428
+ res.end();
429
+ return;
430
+ }
431
+
432
+ let response = file.content;
433
+
434
+ if (route.entryName) {
435
+ const templateAPI = (0, _template.createTemplateAPI)(file.content.toString());
436
+ await this.emitRouteHook('afterRender', {
437
+ context,
438
+ templateAPI
439
+ });
440
+ await this.injectMicroFE(context, templateAPI);
441
+ templateAPI.appendHead(`<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>`);
442
+ response = templateAPI.get();
443
+ }
444
+
445
+ res.setHeader('content-type', file.contentType);
446
+ res.end(response);
447
+ } // eslint-disable-next-line max-statements
448
+
449
+
450
+ async injectMicroFE(context, templateAPI) {
451
+ var _conf$runtime, _conf$server;
452
+
453
+ const {
454
+ conf
455
+ } = this;
456
+ const masterApp = (_conf$runtime = conf.runtime) === null || _conf$runtime === void 0 ? void 0 : _conf$runtime.masterApp; // no inject if not master App
457
+
458
+ if (!masterApp) {
459
+ return;
460
+ }
461
+
462
+ const manifest = masterApp.manifest || {};
463
+ let modules = [];
464
+ const {
465
+ modules: configModules = []
466
+ } = manifest; // while config modules is an string, fetch data from remote
467
+
468
+ if (typeof configModules === 'string') {
469
+ const moduleRequestUrl = configModules;
470
+
471
+ try {
472
+ const {
473
+ data: remoteModules
474
+ } = await _axios.default.get(moduleRequestUrl);
475
+
476
+ if (Array.isArray(remoteModules)) {
477
+ modules.push(...remoteModules);
478
+ }
479
+ } catch (e) {
480
+ context.error(_constants.ERROR_DIGEST.EMICROINJ, e);
481
+ }
482
+ } else if (Array.isArray(configModules)) {
483
+ modules.push(...configModules);
484
+ }
485
+
486
+ const {
487
+ headers
488
+ } = context.req;
489
+ const debugName = headers['x-micro-frontend-module-name'] || context.query['__debug__micro-frontend-module-name'];
490
+ const debugEntry = headers['x-micro-frontend-module-entry'] || context.query['__debug__micro-frontend-module-entry']; // add debug micro App to first
491
+
492
+ if (debugName && debugEntry && (_conf$server = conf.server) !== null && _conf$server !== void 0 && _conf$server.enableMicroFrontendDebug) {
493
+ modules = modules.map(m => {
494
+ if (m.name === debugName) {
495
+ return {
496
+ name: debugName,
497
+ entry: debugEntry
498
+ };
499
+ }
500
+
501
+ return m;
502
+ });
503
+ }
504
+
505
+ try {
506
+ // Todo Safety xss
507
+ const injection = JSON.stringify(_objectSpread(_objectSpread({}, manifest), {}, {
508
+ modules
509
+ }));
510
+ templateAPI.appendHead(`<script>window.modern_manifest=${injection}</script>`);
511
+ } catch (e) {
512
+ context.error(_constants.ERROR_DIGEST.EMICROINJ, e);
513
+ }
514
+ } // compose handlers and create the final handler
515
+
516
+
517
+ compose() {
518
+ const {
519
+ handlers
520
+ } = this;
521
+
522
+ if (!Array.isArray(handlers)) {
523
+ throw new TypeError('Middleware stack must be an array!');
524
+ }
525
+
526
+ for (const fn of handlers) {
527
+ if (typeof fn !== 'function') {
528
+ throw new TypeError('Middleware must be composed of functions!');
529
+ }
530
+ }
531
+
532
+ this._handler = (context, next) => {
533
+ let i = 0;
534
+
535
+ const dispatch = () => {
536
+ const handler = handlers[i++];
537
+
538
+ if (!handler) {
539
+ return next();
540
+ } // eslint-disable-next-line promise/prefer-await-to-then
541
+
542
+
543
+ return handler(context, dispatch).catch(onError);
544
+ };
545
+
546
+ const onError = err => {
547
+ this.onError(context, err);
548
+ };
549
+
550
+ return dispatch();
551
+ };
552
+ }
553
+
554
+ requestHandler(req, res, next = () => {// empty
555
+ }) {
556
+ res.statusCode = 200;
557
+ req.logger = req.logger || this.logger;
558
+ req.metrics = req.metrics || this.metrics;
559
+ const context = (0, _context.createContext)(req, res);
560
+
561
+ try {
562
+ this._handler(context, next);
563
+ } catch (err) {
564
+ this.onError(context, err);
565
+ }
566
+ }
567
+
568
+ onError(context, err) {
569
+ context.error(_constants.ERROR_DIGEST.EINTER, err);
570
+ this.renderErrorPage(context, 500);
571
+ }
572
+
573
+ async renderErrorPage(context, status) {
574
+ const {
575
+ res
576
+ } = context;
577
+ context.status = status;
578
+ res.setHeader('content-type', _mimeTypes.default.contentType('html'));
579
+ const statusPage = `/${status}`;
580
+ const customErrorPage = `/_error`;
581
+ const matched = this.router.match(statusPage) || this.router.match(customErrorPage); // if no custom status page find
582
+
583
+ if (matched) {
584
+ const route = matched.generate(context.url);
585
+ const {
586
+ entryName
587
+ } = route; // check entryName, aviod matched '/' route
588
+
589
+ if (entryName === status.toString() || entryName === '_error') {
590
+ try {
591
+ const file = await this.routeRenderHandler({
592
+ route,
593
+ ctx: context,
594
+ runner: this.runner
595
+ });
596
+
597
+ if (file) {
598
+ context.res.end(file.content);
599
+ return;
600
+ }
601
+ } catch (e) {// just catch error when the rendering error occurred in the custom error page.
602
+ }
603
+ }
604
+ }
605
+
606
+ const text = _constants.ERROR_PAGE_TEXT[status] || _constants.ERROR_PAGE_TEXT[500];
607
+ res.end((0, _utils2.createErrorDocument)(status, text));
608
+ }
609
+
610
+ }
611
+ /* eslint-enable max-lines */
612
+
613
+
614
+ exports.ModernServer = ModernServer;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });