@modern-js/prod-server 1.21.5 → 2.0.0-beta.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/CHANGELOG.md +91 -10
- package/dist/js/modern/constants.js +0 -2
- package/dist/js/modern/index.js +0 -1
- package/dist/js/modern/libs/context/context.js +10 -56
- package/dist/js/modern/libs/hook-api/index.js +125 -0
- package/dist/js/modern/libs/hook-api/route.js +13 -36
- package/dist/js/modern/libs/hook-api/template.js +38 -15
- package/dist/js/modern/libs/loadConfig.js +3 -10
- package/dist/js/modern/libs/metrics.js +6 -6
- package/dist/js/modern/libs/proxy.js +7 -12
- package/dist/js/modern/libs/render/cache/__tests__/cache.fun.test.js +0 -1
- package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +0 -9
- package/dist/js/modern/libs/render/cache/index.js +37 -28
- package/dist/js/modern/libs/render/cache/page-caches/lru.js +0 -10
- package/dist/js/modern/libs/render/cache/spr.js +12 -62
- package/dist/js/modern/libs/render/cache/util.js +0 -6
- package/dist/js/modern/libs/render/index.js +6 -11
- package/dist/js/modern/libs/render/measure.js +7 -10
- package/dist/js/modern/libs/render/modern/index.js +2 -13
- package/dist/js/modern/libs/render/reader.js +13 -24
- package/dist/js/modern/libs/render/ssr.js +24 -12
- package/dist/js/modern/libs/render/static.js +6 -9
- package/dist/js/modern/libs/render/type.js +0 -1
- package/dist/js/modern/libs/route/index.js +8 -19
- package/dist/js/modern/libs/route/matcher.js +21 -29
- package/dist/js/modern/libs/route/route.js +0 -13
- package/dist/js/modern/libs/serve-file.js +13 -6
- package/dist/js/modern/server/index.js +27 -43
- package/dist/js/modern/server/modern-server-split.js +5 -55
- package/dist/js/modern/server/modern-server.js +179 -250
- package/dist/js/modern/utils.js +2 -21
- package/dist/js/modern/worker-server.js +34 -0
- package/dist/js/node/constants.js +0 -2
- package/dist/js/node/index.js +0 -10
- package/dist/js/node/libs/context/context.js +10 -65
- package/dist/js/node/libs/context/index.js +0 -3
- package/dist/js/node/libs/hook-api/index.js +136 -0
- package/dist/js/node/libs/hook-api/route.js +13 -38
- package/dist/js/node/libs/hook-api/template.js +40 -18
- package/dist/js/node/libs/loadConfig.js +3 -22
- package/dist/js/node/libs/metrics.js +6 -6
- package/dist/js/node/libs/proxy.js +7 -17
- package/dist/js/node/libs/render/cache/__tests__/cache.fun.test.js +0 -5
- package/dist/js/node/libs/render/cache/__tests__/cache.test.js +0 -12
- package/dist/js/node/libs/render/cache/index.js +37 -33
- package/dist/js/node/libs/render/cache/page-caches/index.js +0 -2
- package/dist/js/node/libs/render/cache/page-caches/lru.js +0 -14
- package/dist/js/node/libs/render/cache/spr.js +12 -71
- package/dist/js/node/libs/render/cache/util.js +0 -18
- package/dist/js/node/libs/render/index.js +6 -26
- package/dist/js/node/libs/render/measure.js +5 -15
- package/dist/js/node/libs/render/modern/index.js +2 -20
- package/dist/js/node/libs/render/reader.js +12 -39
- package/dist/js/node/libs/render/ssr.js +23 -22
- package/dist/js/node/libs/render/static.js +6 -18
- package/dist/js/node/libs/render/type.js +0 -1
- package/dist/js/node/libs/route/index.js +8 -22
- package/dist/js/node/libs/route/matcher.js +18 -34
- package/dist/js/node/libs/route/route.js +0 -15
- package/dist/js/node/libs/serve-file.js +15 -12
- package/dist/js/node/server/index.js +26 -62
- package/dist/js/node/server/modern-server-split.js +5 -58
- package/dist/js/node/server/modern-server.js +178 -280
- package/dist/js/node/utils.js +3 -46
- package/dist/js/node/worker-server.js +41 -0
- package/dist/js/treeshaking/constants.js +28 -0
- package/dist/js/treeshaking/index.js +13 -0
- package/dist/js/treeshaking/libs/context/context.js +243 -0
- package/dist/js/treeshaking/libs/context/index.js +5 -0
- package/dist/js/treeshaking/libs/hook-api/index.js +157 -0
- package/dist/js/treeshaking/libs/hook-api/route.js +33 -0
- package/dist/js/treeshaking/libs/hook-api/template.js +91 -0
- package/dist/js/treeshaking/libs/loadConfig.js +39 -0
- package/dist/js/treeshaking/libs/metrics.js +12 -0
- package/dist/js/treeshaking/libs/proxy.js +80 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cache.fun.test.js +124 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cache.test.js +464 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cacheable.js +53 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/error-configuration.js +35 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/matched-cache.js +121 -0
- package/dist/js/treeshaking/libs/render/cache/index.js +184 -0
- package/dist/js/treeshaking/libs/render/cache/page-caches/index.js +30 -0
- package/dist/js/treeshaking/libs/render/cache/page-caches/lru.js +46 -0
- package/dist/js/treeshaking/libs/render/cache/spr.js +362 -0
- package/dist/js/treeshaking/libs/render/cache/type.js +1 -0
- package/dist/js/treeshaking/libs/render/cache/util.js +101 -0
- package/dist/js/treeshaking/libs/render/index.js +100 -0
- package/dist/js/treeshaking/libs/render/measure.js +61 -0
- package/dist/js/treeshaking/libs/render/modern/browser-list.js +7 -0
- package/dist/js/treeshaking/libs/render/modern/index.js +39 -0
- package/dist/js/treeshaking/libs/render/reader.js +191 -0
- package/dist/js/treeshaking/libs/render/ssr.js +98 -0
- package/dist/js/treeshaking/libs/render/static.js +84 -0
- package/dist/js/treeshaking/libs/render/type.js +6 -0
- package/dist/js/treeshaking/libs/route/index.js +94 -0
- package/dist/js/treeshaking/libs/route/matcher.js +113 -0
- package/dist/js/treeshaking/libs/route/route.js +26 -0
- package/dist/js/treeshaking/libs/serve-file.js +75 -0
- package/dist/js/treeshaking/server/index.js +343 -0
- package/dist/js/treeshaking/server/modern-server-split.js +152 -0
- package/dist/js/treeshaking/server/modern-server.js +945 -0
- package/dist/js/treeshaking/type.js +1 -0
- package/dist/js/treeshaking/utils.js +87 -0
- package/dist/js/treeshaking/worker-server.js +56 -0
- package/dist/types/index.d.ts +0 -2
- package/dist/types/libs/context/context.d.ts +0 -3
- package/dist/types/libs/hook-api/index.d.ts +5 -0
- package/dist/types/libs/hook-api/route.d.ts +9 -14
- package/dist/types/libs/hook-api/template.d.ts +19 -9
- package/dist/types/libs/loadConfig.d.ts +0 -1
- package/dist/types/libs/render/cache/index.d.ts +4 -4
- package/dist/types/libs/render/cache/spr.d.ts +0 -2
- package/dist/types/libs/render/type.d.ts +3 -1
- package/dist/types/libs/serve-file.d.ts +2 -1
- package/dist/types/server/index.d.ts +2 -3
- package/dist/types/server/modern-server.d.ts +11 -11
- package/dist/types/type.d.ts +8 -10
- package/dist/types/utils.d.ts +0 -1
- package/dist/types/worker-server.d.ts +16 -0
- package/package.json +28 -35
|
@@ -4,64 +4,38 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.ModernServer = void 0;
|
|
7
|
-
|
|
8
7
|
var _http = require("http");
|
|
9
|
-
|
|
10
8
|
var _util = _interopRequireDefault(require("util"));
|
|
11
|
-
|
|
12
9
|
var _path = _interopRequireDefault(require("path"));
|
|
13
|
-
|
|
14
10
|
var _utils = require("@modern-js/utils");
|
|
15
|
-
|
|
16
|
-
var _axios = _interopRequireDefault(require("axios"));
|
|
17
|
-
|
|
18
|
-
var _lodash = require("@modern-js/utils/lodash");
|
|
19
|
-
|
|
20
11
|
var _route = require("../libs/route");
|
|
21
|
-
|
|
22
12
|
var _render = require("../libs/render");
|
|
23
|
-
|
|
24
13
|
var _serveFile = require("../libs/serve-file");
|
|
25
|
-
|
|
26
14
|
var _utils2 = require("../utils");
|
|
27
|
-
|
|
28
15
|
var reader = _interopRequireWildcard(require("../libs/render/reader"));
|
|
29
|
-
|
|
30
16
|
var _proxy = require("../libs/proxy");
|
|
31
|
-
|
|
32
17
|
var _context = require("../libs/context");
|
|
33
|
-
|
|
34
|
-
var _constants = require("../constants");
|
|
35
|
-
|
|
36
18
|
var _template = require("../libs/hook-api/template");
|
|
37
|
-
|
|
38
|
-
var
|
|
39
|
-
|
|
19
|
+
var _constants = require("../constants");
|
|
20
|
+
var _hookApi = require("../libs/hook-api");
|
|
40
21
|
const _excluded = ["getMiddlewares"];
|
|
41
|
-
|
|
42
22
|
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); }
|
|
43
|
-
|
|
44
23
|
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; }
|
|
45
|
-
|
|
46
24
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
47
|
-
|
|
48
25
|
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; }
|
|
49
|
-
|
|
50
26
|
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; }
|
|
51
|
-
|
|
52
27
|
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; }
|
|
53
|
-
|
|
54
28
|
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; }
|
|
55
|
-
|
|
56
29
|
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; }
|
|
57
|
-
|
|
58
30
|
const API_DIR = './api';
|
|
59
31
|
const SERVER_DIR = './server';
|
|
60
|
-
|
|
61
32
|
class ModernServer {
|
|
62
33
|
// appDirectory
|
|
34
|
+
|
|
63
35
|
// product dist dir
|
|
36
|
+
|
|
64
37
|
// work on src or dist
|
|
38
|
+
|
|
65
39
|
constructor({
|
|
66
40
|
pwd,
|
|
67
41
|
config,
|
|
@@ -73,49 +47,28 @@ class ModernServer {
|
|
|
73
47
|
proxyTarget
|
|
74
48
|
}) {
|
|
75
49
|
var _config$output;
|
|
76
|
-
|
|
77
50
|
_defineProperty(this, "pwd", void 0);
|
|
78
|
-
|
|
79
51
|
_defineProperty(this, "distDir", void 0);
|
|
80
|
-
|
|
81
52
|
_defineProperty(this, "workDir", void 0);
|
|
82
|
-
|
|
83
53
|
_defineProperty(this, "router", void 0);
|
|
84
|
-
|
|
85
54
|
_defineProperty(this, "conf", void 0);
|
|
86
|
-
|
|
87
55
|
_defineProperty(this, "handlers", []);
|
|
88
|
-
|
|
89
56
|
_defineProperty(this, "presetRoutes", void 0);
|
|
90
|
-
|
|
91
57
|
_defineProperty(this, "runner", void 0);
|
|
92
|
-
|
|
93
58
|
_defineProperty(this, "logger", void 0);
|
|
94
|
-
|
|
95
59
|
_defineProperty(this, "metrics", void 0);
|
|
96
|
-
|
|
97
60
|
_defineProperty(this, "runMode", void 0);
|
|
98
|
-
|
|
99
61
|
_defineProperty(this, "reader", reader);
|
|
100
|
-
|
|
101
62
|
_defineProperty(this, "proxyTarget", void 0);
|
|
102
|
-
|
|
103
63
|
_defineProperty(this, "staticFileHandler", void 0);
|
|
104
|
-
|
|
105
64
|
_defineProperty(this, "routeRenderHandler", void 0);
|
|
106
|
-
|
|
65
|
+
_defineProperty(this, "beforeRouteHandler", null);
|
|
107
66
|
_defineProperty(this, "frameWebHandler", null);
|
|
108
|
-
|
|
109
67
|
_defineProperty(this, "frameAPIHandler", null);
|
|
110
|
-
|
|
111
68
|
_defineProperty(this, "proxyHandler", null);
|
|
112
|
-
|
|
113
69
|
_defineProperty(this, "_handler", void 0);
|
|
114
|
-
|
|
115
70
|
_defineProperty(this, "staticGenerate", void 0);
|
|
116
|
-
|
|
117
71
|
require('ignore-styles');
|
|
118
|
-
|
|
119
72
|
this.pwd = pwd;
|
|
120
73
|
this.distDir = _path.default.join(pwd, ((_config$output = config.output) === null || _config$output === void 0 ? void 0 : _config$output.path) || 'dist');
|
|
121
74
|
this.workDir = this.distDir;
|
|
@@ -127,43 +80,45 @@ class ModernServer {
|
|
|
127
80
|
this.presetRoutes = routes;
|
|
128
81
|
this.proxyTarget = proxyTarget;
|
|
129
82
|
this.staticGenerate = staticGenerate || false;
|
|
130
|
-
this.runMode = runMode || _constants.RUN_MODE.
|
|
131
|
-
process.env.BUILD_TYPE = `${this.staticGenerate ? 'ssg' : 'ssr'}`;
|
|
132
|
-
}
|
|
133
|
-
|
|
83
|
+
this.runMode = runMode || _constants.RUN_MODE.FULL;
|
|
84
|
+
// process.env.BUILD_TYPE = `${this.staticGenerate ? 'ssg' : 'ssr'}`;
|
|
85
|
+
}
|
|
134
86
|
|
|
87
|
+
// server prepare
|
|
135
88
|
async onInit(runner, app) {
|
|
136
89
|
var _conf$bff;
|
|
137
|
-
|
|
138
90
|
this.runner = runner;
|
|
139
91
|
const {
|
|
140
92
|
distDir,
|
|
141
93
|
staticGenerate,
|
|
142
94
|
conf
|
|
143
95
|
} = this;
|
|
144
|
-
(0, _utils2.debug)('final server conf', this.conf);
|
|
145
|
-
|
|
96
|
+
(0, _utils2.debug)('final server conf', this.conf);
|
|
97
|
+
// proxy handler, each proxy has own handler
|
|
146
98
|
this.proxyHandler = (0, _proxy.createProxyHandler)((_conf$bff = conf.bff) === null || _conf$bff === void 0 ? void 0 : _conf$bff.proxy);
|
|
147
|
-
|
|
148
99
|
if (this.proxyHandler) {
|
|
149
100
|
this.proxyHandler.forEach(handler => {
|
|
150
101
|
this.addHandler(handler);
|
|
151
102
|
});
|
|
152
|
-
}
|
|
153
|
-
|
|
103
|
+
}
|
|
154
104
|
|
|
105
|
+
// start file reader
|
|
155
106
|
this.reader.init();
|
|
156
107
|
app.on('close', () => {
|
|
157
108
|
this.reader.close();
|
|
158
|
-
});
|
|
109
|
+
});
|
|
159
110
|
|
|
111
|
+
// use preset routes priority
|
|
160
112
|
const usageRoutes = this.filterRoutes(this.getRoutes());
|
|
161
|
-
this.router.reset(usageRoutes);
|
|
113
|
+
this.router.reset(usageRoutes);
|
|
162
114
|
|
|
115
|
+
// warmup ssr bundle in production env
|
|
163
116
|
this.warmupSSRBundle();
|
|
164
|
-
await this.prepareFrameHandler();
|
|
165
|
-
|
|
117
|
+
await this.prepareFrameHandler();
|
|
118
|
+
await this.prepareBeforeRouteHandler(usageRoutes, distDir);
|
|
166
119
|
|
|
120
|
+
// Only work when without setting `assetPrefix`.
|
|
121
|
+
// Setting `assetPrefix` means these resources should be uploaded to CDN.
|
|
167
122
|
const staticPathRegExp = (0, _utils2.getStaticReg)(this.conf.output || {});
|
|
168
123
|
this.staticFileHandler = (0, _serveFile.createStaticFileHandler)([{
|
|
169
124
|
path: staticPathRegExp,
|
|
@@ -175,15 +130,32 @@ class ModernServer {
|
|
|
175
130
|
});
|
|
176
131
|
await this.setupBeforeProdMiddleware();
|
|
177
132
|
this.addHandler(this.staticFileHandler);
|
|
178
|
-
this.addHandler(this.routeHandler.bind(this)); // compose middlewares to http handler
|
|
179
|
-
|
|
180
|
-
this.compose();
|
|
181
|
-
} // server ready
|
|
182
133
|
|
|
134
|
+
// execute after staticFileHandler, can rename to staticFallbackHandler if needed.
|
|
135
|
+
this.addHandler(_serveFile.faviconFallbackHandler);
|
|
136
|
+
this.addBeforeRouteHandler();
|
|
137
|
+
this.addHandler(this.routeHandler.bind(this));
|
|
183
138
|
|
|
184
|
-
|
|
139
|
+
// compose middlewares to http handler
|
|
140
|
+
this.compose();
|
|
185
141
|
}
|
|
186
142
|
|
|
143
|
+
// server ready
|
|
144
|
+
onRepack(_) {
|
|
145
|
+
// empty
|
|
146
|
+
}
|
|
147
|
+
addBeforeRouteHandler() {
|
|
148
|
+
this.addHandler(async (context, next) => {
|
|
149
|
+
if (this.beforeRouteHandler) {
|
|
150
|
+
await this.beforeRouteHandler(context);
|
|
151
|
+
if (this.isSend(context.res)) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// eslint-disable-next-line consistent-return
|
|
156
|
+
return next();
|
|
157
|
+
});
|
|
158
|
+
}
|
|
187
159
|
onServerChange({
|
|
188
160
|
filepath
|
|
189
161
|
}) {
|
|
@@ -194,66 +166,85 @@ class ModernServer {
|
|
|
194
166
|
api,
|
|
195
167
|
server
|
|
196
168
|
} = _constants.AGGRED_DIR;
|
|
197
|
-
|
|
198
169
|
const apiPath = _path.default.normalize(_path.default.join(pwd, api));
|
|
199
|
-
|
|
200
170
|
const serverPath = _path.default.normalize(_path.default.join(pwd, server));
|
|
201
|
-
|
|
202
171
|
const onlyApi = filepath.startsWith(apiPath);
|
|
203
172
|
const onlyWeb = filepath.startsWith(serverPath);
|
|
204
173
|
this.prepareFrameHandler({
|
|
205
174
|
onlyWeb,
|
|
206
175
|
onlyApi
|
|
207
176
|
});
|
|
208
|
-
}
|
|
209
|
-
|
|
177
|
+
}
|
|
210
178
|
|
|
179
|
+
// exposed requestHandler
|
|
211
180
|
getRequestHandler() {
|
|
212
181
|
return this.requestHandler.bind(this);
|
|
213
182
|
}
|
|
214
|
-
|
|
183
|
+
async render(req, res, url) {
|
|
184
|
+
req.logger = this.logger;
|
|
185
|
+
req.metrics = this.metrics;
|
|
186
|
+
const context = (0, _context.createContext)(req, res);
|
|
187
|
+
const matched = this.router.match(url || context.path);
|
|
188
|
+
if (!matched) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const route = matched.generate(context.url);
|
|
192
|
+
const result = await this.handleWeb(context, route);
|
|
193
|
+
if (!result) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
return result.content.toString();
|
|
197
|
+
}
|
|
215
198
|
async createHTTPServer(handler) {
|
|
216
199
|
return (0, _http.createServer)(handler);
|
|
217
200
|
}
|
|
201
|
+
|
|
218
202
|
/* —————————————————————— function will be overwrite —————————————————————— */
|
|
219
203
|
// get routes info
|
|
220
|
-
|
|
221
|
-
|
|
222
204
|
getRoutes() {
|
|
223
205
|
// Preferred to use preset routes
|
|
224
206
|
if (this.presetRoutes) {
|
|
225
207
|
return this.presetRoutes;
|
|
226
|
-
}
|
|
227
|
-
|
|
208
|
+
}
|
|
228
209
|
|
|
210
|
+
// read routes from spec file
|
|
229
211
|
const file = _path.default.join(this.distDir, _utils.ROUTE_SPEC_FILE);
|
|
230
|
-
|
|
231
212
|
if (_utils.fs.existsSync(file)) {
|
|
232
213
|
const content = _utils.fs.readJSONSync(file);
|
|
233
|
-
|
|
234
214
|
return content.routes;
|
|
235
215
|
}
|
|
236
|
-
|
|
237
216
|
return [];
|
|
238
|
-
}
|
|
239
|
-
// handler should do not do more things after invoke next
|
|
240
|
-
|
|
217
|
+
}
|
|
241
218
|
|
|
219
|
+
// add promisify request handler to server
|
|
220
|
+
// handler should do not do more things after invoke next
|
|
242
221
|
addHandler(handler) {
|
|
243
222
|
if (handler[Symbol.toStringTag] === 'AsyncFunction') {
|
|
244
223
|
this.handlers.push(handler);
|
|
245
224
|
} else {
|
|
246
225
|
this.handlers.push(_util.default.promisify(handler));
|
|
247
226
|
}
|
|
248
|
-
}
|
|
249
|
-
|
|
227
|
+
}
|
|
250
228
|
|
|
229
|
+
// return 404 page
|
|
251
230
|
render404(context) {
|
|
252
231
|
context.error(_constants.ERROR_DIGEST.ENOTF, '404 Not Found');
|
|
253
232
|
this.renderErrorPage(context, 404);
|
|
254
|
-
}
|
|
255
|
-
|
|
233
|
+
}
|
|
234
|
+
async prepareBeforeRouteHandler(specs, distDir) {
|
|
235
|
+
const {
|
|
236
|
+
runner
|
|
237
|
+
} = this;
|
|
238
|
+
const handler = await runner.preparebeforeRouteHandler({
|
|
239
|
+
serverRoutes: specs,
|
|
240
|
+
distDir
|
|
241
|
+
}, {
|
|
242
|
+
onLast: () => null
|
|
243
|
+
});
|
|
244
|
+
this.beforeRouteHandler = handler;
|
|
245
|
+
}
|
|
256
246
|
|
|
247
|
+
// gather frame extension and get framework handler
|
|
257
248
|
async prepareFrameHandler(options) {
|
|
258
249
|
const {
|
|
259
250
|
workDir,
|
|
@@ -262,49 +253,45 @@ class ModernServer {
|
|
|
262
253
|
const {
|
|
263
254
|
onlyApi,
|
|
264
255
|
onlyWeb
|
|
265
|
-
} = options || {};
|
|
256
|
+
} = options || {};
|
|
266
257
|
|
|
258
|
+
// server hook, gather plugin inject
|
|
267
259
|
const _createMiddlewareColl = (0, _utils2.createMiddlewareCollecter)(),
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
260
|
+
{
|
|
261
|
+
getMiddlewares
|
|
262
|
+
} = _createMiddlewareColl,
|
|
263
|
+
collector = _objectWithoutProperties(_createMiddlewareColl, _excluded);
|
|
273
264
|
await runner.gather(collector);
|
|
274
265
|
const {
|
|
275
266
|
api: pluginAPIExt,
|
|
276
267
|
web: pluginWebExt
|
|
277
268
|
} = getMiddlewares();
|
|
278
|
-
|
|
279
269
|
const apiDir = _path.default.join(workDir, API_DIR);
|
|
270
|
+
const serverDir = _path.default.join(workDir, SERVER_DIR);
|
|
280
271
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
272
|
+
// get api or web server handler from server-framework plugin
|
|
284
273
|
if ((await _utils.fs.pathExists(_path.default.join(serverDir))) && !onlyApi) {
|
|
285
274
|
const webExtension = (0, _utils2.mergeExtension)(pluginWebExt);
|
|
286
275
|
this.frameWebHandler = await this.prepareWebHandler(webExtension);
|
|
287
276
|
}
|
|
288
|
-
|
|
289
277
|
if (_utils.fs.existsSync(apiDir) && !onlyWeb) {
|
|
290
278
|
const apiExtension = (0, _utils2.mergeExtension)(pluginAPIExt);
|
|
291
279
|
this.frameAPIHandler = await this.prepareAPIHandler(apiExtension);
|
|
292
280
|
}
|
|
293
281
|
}
|
|
294
|
-
|
|
295
282
|
async prepareWebHandler(extension) {
|
|
296
283
|
const {
|
|
297
284
|
workDir,
|
|
298
285
|
runner
|
|
299
286
|
} = this;
|
|
300
|
-
|
|
287
|
+
const handler = await runner.prepareWebServer({
|
|
301
288
|
pwd: workDir,
|
|
302
289
|
config: extension
|
|
303
290
|
}, {
|
|
304
291
|
onLast: () => null
|
|
305
292
|
});
|
|
293
|
+
return handler;
|
|
306
294
|
}
|
|
307
|
-
|
|
308
295
|
async prepareAPIHandler(extension) {
|
|
309
296
|
const {
|
|
310
297
|
workDir,
|
|
@@ -323,18 +310,9 @@ class ModernServer {
|
|
|
323
310
|
onLast: () => null
|
|
324
311
|
});
|
|
325
312
|
}
|
|
326
|
-
|
|
327
313
|
filterRoutes(routes) {
|
|
328
314
|
return routes;
|
|
329
315
|
}
|
|
330
|
-
|
|
331
|
-
async emitRouteHook(eventName, input) {
|
|
332
|
-
input.context = (0, _lodash.clone)(input.context);
|
|
333
|
-
return this.runner[eventName](input, {
|
|
334
|
-
onLast: _utils2.noop
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
|
|
338
316
|
async setupBeforeProdMiddleware() {
|
|
339
317
|
const {
|
|
340
318
|
conf,
|
|
@@ -345,20 +323,16 @@ class ModernServer {
|
|
|
345
323
|
this.addHandler(mid);
|
|
346
324
|
});
|
|
347
325
|
}
|
|
348
|
-
|
|
349
326
|
async handleAPI(context) {
|
|
350
327
|
const {
|
|
351
328
|
req,
|
|
352
329
|
res
|
|
353
330
|
} = context;
|
|
354
|
-
|
|
355
331
|
if (!this.frameAPIHandler) {
|
|
356
332
|
throw new Error('can not found api handler');
|
|
357
333
|
}
|
|
358
|
-
|
|
359
334
|
await this.frameAPIHandler(req, res);
|
|
360
335
|
}
|
|
361
|
-
|
|
362
336
|
async handleWeb(context, route) {
|
|
363
337
|
return this.routeRenderHandler({
|
|
364
338
|
ctx: context,
|
|
@@ -366,273 +340,198 @@ class ModernServer {
|
|
|
366
340
|
runner: this.runner
|
|
367
341
|
});
|
|
368
342
|
}
|
|
369
|
-
|
|
370
343
|
async proxy() {
|
|
371
344
|
return null;
|
|
372
|
-
}
|
|
373
|
-
|
|
345
|
+
}
|
|
374
346
|
|
|
347
|
+
// warmup ssr function
|
|
375
348
|
warmupSSRBundle() {
|
|
376
349
|
const {
|
|
377
350
|
distDir
|
|
378
351
|
} = this;
|
|
379
352
|
const bundles = this.router.getBundles();
|
|
380
353
|
bundles.forEach(bundle => {
|
|
381
|
-
const filepath = _path.default.join(distDir, bundle);
|
|
382
|
-
|
|
383
|
-
|
|
354
|
+
const filepath = _path.default.join(distDir, bundle);
|
|
355
|
+
// if error, just throw and let process die
|
|
384
356
|
require(filepath);
|
|
385
357
|
});
|
|
386
358
|
}
|
|
387
|
-
|
|
388
359
|
createContext(req, res, options = {}) {
|
|
389
360
|
return (0, _context.createContext)(req, res, options);
|
|
390
361
|
}
|
|
362
|
+
|
|
391
363
|
/* —————————————————————— private function —————————————————————— */
|
|
392
364
|
// handler route.json, include api / csr / ssr
|
|
393
|
-
|
|
394
|
-
|
|
395
365
|
async routeHandler(context) {
|
|
396
366
|
const {
|
|
397
|
-
req,
|
|
398
367
|
res
|
|
399
368
|
} = context;
|
|
400
|
-
await this.emitRouteHook('beforeMatch', {
|
|
401
|
-
context
|
|
402
|
-
}); // match routes in the route spec
|
|
403
369
|
|
|
370
|
+
// match routes in the route spec
|
|
404
371
|
const matched = this.router.match(context.path);
|
|
405
|
-
|
|
406
372
|
if (!matched) {
|
|
407
373
|
this.render404(context);
|
|
408
374
|
return;
|
|
409
375
|
}
|
|
410
376
|
|
|
411
|
-
|
|
377
|
+
// route is api service
|
|
378
|
+
let route = matched.generate(context.url);
|
|
379
|
+
if (route.isApi) {
|
|
380
|
+
await this.handleAPI(context);
|
|
412
381
|
return;
|
|
413
382
|
}
|
|
383
|
+
const afterMatchContext = (0, _hookApi.createAfterMatchContext)(context, route.entryName);
|
|
414
384
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
385
|
+
// only full mode run server hook
|
|
386
|
+
if (this.runMode === _constants.RUN_MODE.FULL) {
|
|
387
|
+
await this.runner.afterMatch(afterMatchContext, {
|
|
388
|
+
onLast: _utils2.noop
|
|
389
|
+
});
|
|
390
|
+
}
|
|
421
391
|
if (this.isSend(res)) {
|
|
422
392
|
return;
|
|
423
393
|
}
|
|
424
|
-
|
|
425
394
|
const {
|
|
426
|
-
current
|
|
427
|
-
|
|
428
|
-
|
|
395
|
+
current,
|
|
396
|
+
url,
|
|
397
|
+
status
|
|
398
|
+
} = afterMatchContext.router;
|
|
399
|
+
// redirect to another url
|
|
400
|
+
if (url) {
|
|
401
|
+
this.redirect(res, url, status);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// rewrite to another entry
|
|
406
|
+
if (route.entryName !== current) {
|
|
407
|
+
const matched = this.router.matchEntry(current);
|
|
408
|
+
if (!matched) {
|
|
409
|
+
this.render404(context);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
route = matched.generate(context.url);
|
|
413
|
+
}
|
|
429
414
|
context.setParams(route.params);
|
|
430
415
|
context.setServerData('router', {
|
|
431
416
|
baseUrl: route.urlPath,
|
|
432
417
|
params: route.params
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
if (route.isApi) {
|
|
436
|
-
await this.handleAPI(context);
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
|
|
418
|
+
});
|
|
440
419
|
if (this.frameWebHandler) {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
420
|
+
res.locals = res.locals || {};
|
|
421
|
+
const middlewareContext = (0, _hookApi.createMiddlewareContext)(context);
|
|
422
|
+
await this.frameWebHandler(middlewareContext);
|
|
423
|
+
res.locals = _objectSpread(_objectSpread({}, res.locals), middlewareContext.response.locals);
|
|
424
|
+
}
|
|
444
425
|
|
|
426
|
+
// frameWebHandler has process request
|
|
445
427
|
if (this.isSend(res)) {
|
|
446
428
|
return;
|
|
447
429
|
}
|
|
448
|
-
|
|
449
430
|
if (route.responseHeaders) {
|
|
450
431
|
Object.keys(route.responseHeaders).forEach(key => {
|
|
451
432
|
const value = route.responseHeaders[key];
|
|
452
|
-
|
|
453
433
|
if (value) {
|
|
454
434
|
context.res.setHeader(key, value);
|
|
455
435
|
}
|
|
456
436
|
});
|
|
457
437
|
}
|
|
458
|
-
|
|
459
|
-
if (
|
|
460
|
-
await this.emitRouteHook('beforeRender', {
|
|
461
|
-
context
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const file = await this.handleWeb(context, route);
|
|
466
|
-
|
|
467
|
-
if (!file) {
|
|
438
|
+
const renderResult = await this.handleWeb(context, route);
|
|
439
|
+
if (!renderResult) {
|
|
468
440
|
this.render404(context);
|
|
469
441
|
return;
|
|
470
442
|
}
|
|
471
443
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
res.end();
|
|
444
|
+
// React Router navigation
|
|
445
|
+
if (renderResult.redirect) {
|
|
446
|
+
this.redirect(res, renderResult.content, renderResult.statusCode);
|
|
476
447
|
return;
|
|
477
448
|
}
|
|
478
|
-
|
|
479
449
|
if (this.isSend(res)) {
|
|
480
450
|
return;
|
|
481
451
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
452
|
+
res.setHeader('content-type', renderResult.contentType);
|
|
453
|
+
const {
|
|
454
|
+
contentStream
|
|
455
|
+
} = renderResult;
|
|
456
|
+
if (contentStream) {
|
|
457
|
+
contentStream.pipe((0, _template.templateInjectableStream)({
|
|
458
|
+
prependHead: route.entryName ? `<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>` : undefined
|
|
459
|
+
})).pipe(res);
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
let response = renderResult.content;
|
|
485
463
|
if (route.entryName) {
|
|
486
|
-
const
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
464
|
+
const afterRenderContext = (0, _hookApi.createAfterRenderContext)(context, response.toString());
|
|
465
|
+
|
|
466
|
+
// only full mode run server hook
|
|
467
|
+
// FIXME: how to run server hook in streaming
|
|
468
|
+
if (this.runMode === _constants.RUN_MODE.FULL) {
|
|
469
|
+
await this.runner.afterRender(afterRenderContext, {
|
|
470
|
+
onLast: _utils2.noop
|
|
471
|
+
});
|
|
472
|
+
}
|
|
492
473
|
if (this.isSend(res)) {
|
|
493
474
|
return;
|
|
494
475
|
}
|
|
495
476
|
|
|
496
|
-
|
|
477
|
+
// It will inject _SERVER_DATA twice, when SSG mode.
|
|
497
478
|
// The first time was in ssg html created, the seoncd time was in prod-server start.
|
|
498
479
|
// but the second wound causes route error.
|
|
499
480
|
// To ensure that the second injection fails, the _SERVER_DATA inject at the front of head,
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
response = templateAPI.get();
|
|
481
|
+
afterRenderContext.template.prependHead(`<script>window._SERVER_DATA=${JSON.stringify(context.serverData)}</script>`);
|
|
482
|
+
response = afterRenderContext.template.get();
|
|
503
483
|
}
|
|
504
|
-
|
|
505
|
-
res.setHeader('content-type', file.contentType);
|
|
506
484
|
res.end(response);
|
|
507
485
|
}
|
|
508
|
-
|
|
509
486
|
isSend(res) {
|
|
510
487
|
if (res.headersSent) {
|
|
511
488
|
return true;
|
|
512
489
|
}
|
|
513
|
-
|
|
514
490
|
if (res.getHeader('Location') && (0, _utils2.isRedirect)(res.statusCode)) {
|
|
515
491
|
res.end();
|
|
516
492
|
return true;
|
|
517
493
|
}
|
|
518
|
-
|
|
519
494
|
return false;
|
|
520
495
|
}
|
|
521
496
|
|
|
522
|
-
|
|
523
|
-
var _conf$runtime, _conf$server;
|
|
524
|
-
|
|
525
|
-
const {
|
|
526
|
-
conf
|
|
527
|
-
} = this;
|
|
528
|
-
const masterApp = (_conf$runtime = conf.runtime) === null || _conf$runtime === void 0 ? void 0 : _conf$runtime.masterApp; // no inject if not master App
|
|
529
|
-
|
|
530
|
-
if (!masterApp) {
|
|
531
|
-
return;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
const manifest = masterApp.manifest || {};
|
|
535
|
-
let modules = [];
|
|
536
|
-
const {
|
|
537
|
-
modules: configModules = []
|
|
538
|
-
} = manifest; // while config modules is an string, fetch data from remote
|
|
539
|
-
|
|
540
|
-
if (typeof configModules === 'string') {
|
|
541
|
-
const moduleRequestUrl = configModules;
|
|
542
|
-
|
|
543
|
-
try {
|
|
544
|
-
const {
|
|
545
|
-
data: remoteModules
|
|
546
|
-
} = await _axios.default.get(moduleRequestUrl);
|
|
547
|
-
|
|
548
|
-
if (Array.isArray(remoteModules)) {
|
|
549
|
-
modules.push(...remoteModules);
|
|
550
|
-
}
|
|
551
|
-
} catch (e) {
|
|
552
|
-
context.error(_constants.ERROR_DIGEST.EMICROINJ, e);
|
|
553
|
-
}
|
|
554
|
-
} else if (Array.isArray(configModules)) {
|
|
555
|
-
modules.push(...configModules);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
const {
|
|
559
|
-
headers
|
|
560
|
-
} = context.req;
|
|
561
|
-
const debugName = headers['x-micro-frontend-module-name'] || context.query['__debug__micro-frontend-module-name'];
|
|
562
|
-
const debugEntry = headers['x-micro-frontend-module-entry'] || context.query['__debug__micro-frontend-module-entry']; // add debug micro App to first
|
|
563
|
-
|
|
564
|
-
if (debugName && debugEntry && (_conf$server = conf.server) !== null && _conf$server !== void 0 && _conf$server.enableMicroFrontendDebug) {
|
|
565
|
-
modules = modules.map(m => {
|
|
566
|
-
if (m.name === debugName) {
|
|
567
|
-
return {
|
|
568
|
-
name: debugName,
|
|
569
|
-
entry: debugEntry
|
|
570
|
-
};
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
return m;
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
try {
|
|
578
|
-
// Todo Safety xss
|
|
579
|
-
const injection = JSON.stringify(_objectSpread(_objectSpread({}, manifest), {}, {
|
|
580
|
-
modules
|
|
581
|
-
}));
|
|
582
|
-
templateAPI.appendHead(`<script>window.modern_manifest=${injection}</script>`);
|
|
583
|
-
} catch (e) {
|
|
584
|
-
context.error(_constants.ERROR_DIGEST.EMICROINJ, e);
|
|
585
|
-
}
|
|
586
|
-
} // compose handlers and create the final handler
|
|
587
|
-
|
|
588
|
-
|
|
497
|
+
// compose handlers and create the final handler
|
|
589
498
|
compose() {
|
|
590
499
|
const {
|
|
591
500
|
handlers
|
|
592
501
|
} = this;
|
|
593
|
-
|
|
594
502
|
if (!Array.isArray(handlers)) {
|
|
595
503
|
throw new TypeError('Middleware stack must be an array!');
|
|
596
504
|
}
|
|
597
|
-
|
|
598
505
|
for (const fn of handlers) {
|
|
599
506
|
if (typeof fn !== 'function') {
|
|
600
507
|
throw new TypeError('Middleware must be composed of functions!');
|
|
601
508
|
}
|
|
602
509
|
}
|
|
603
|
-
|
|
604
510
|
this._handler = (context, next) => {
|
|
605
511
|
let i = 0;
|
|
606
|
-
|
|
607
512
|
const dispatch = error => {
|
|
608
513
|
if (error) {
|
|
609
514
|
return this.onError(context, error);
|
|
610
515
|
}
|
|
611
|
-
|
|
612
516
|
const handler = handlers[i++];
|
|
613
|
-
|
|
614
517
|
if (!handler) {
|
|
615
518
|
return next();
|
|
616
519
|
}
|
|
617
|
-
|
|
618
520
|
return handler(context, dispatch).catch(onError);
|
|
619
521
|
};
|
|
620
|
-
|
|
621
522
|
const onError = err => {
|
|
622
523
|
this.onError(context, err);
|
|
623
524
|
};
|
|
624
|
-
|
|
625
525
|
return dispatch();
|
|
626
526
|
};
|
|
627
527
|
}
|
|
628
|
-
|
|
629
|
-
|
|
528
|
+
requestHandler(req, res, next = () => {
|
|
529
|
+
// empty
|
|
630
530
|
}) {
|
|
631
531
|
res.statusCode = 200;
|
|
632
532
|
req.logger = this.logger;
|
|
633
533
|
req.metrics = this.metrics;
|
|
634
534
|
let context;
|
|
635
|
-
|
|
636
535
|
try {
|
|
637
536
|
context = this.createContext(req, res);
|
|
638
537
|
} catch (e) {
|
|
@@ -641,19 +540,21 @@ class ModernServer {
|
|
|
641
540
|
res.setHeader('content-type', _utils.mime.contentType('html'));
|
|
642
541
|
return res.end((0, _utils2.createErrorDocument)(500, _constants.ERROR_PAGE_TEXT[500]));
|
|
643
542
|
}
|
|
644
|
-
|
|
645
543
|
try {
|
|
646
544
|
return this._handler(context, next);
|
|
647
545
|
} catch (err) {
|
|
648
546
|
return this.onError(context, err);
|
|
649
547
|
}
|
|
650
548
|
}
|
|
651
|
-
|
|
549
|
+
redirect(res, url, status = 302) {
|
|
550
|
+
res.setHeader('Location', url);
|
|
551
|
+
res.statusCode = status;
|
|
552
|
+
res.end();
|
|
553
|
+
}
|
|
652
554
|
onError(context, err) {
|
|
653
555
|
context.error(_constants.ERROR_DIGEST.EINTER, err);
|
|
654
556
|
this.renderErrorPage(context, 500);
|
|
655
557
|
}
|
|
656
|
-
|
|
657
558
|
async renderErrorPage(context, status) {
|
|
658
559
|
const {
|
|
659
560
|
res
|
|
@@ -662,14 +563,15 @@ class ModernServer {
|
|
|
662
563
|
res.setHeader('content-type', _utils.mime.contentType('html'));
|
|
663
564
|
const statusPage = `/${status}`;
|
|
664
565
|
const customErrorPage = `/_error`;
|
|
665
|
-
const matched = this.router.match(statusPage) || this.router.match(customErrorPage);
|
|
566
|
+
const matched = this.router.match(statusPage) || this.router.match(customErrorPage);
|
|
567
|
+
// if no custom status page find
|
|
666
568
|
|
|
667
569
|
if (matched) {
|
|
668
570
|
const route = matched.generate(context.url);
|
|
669
571
|
const {
|
|
670
572
|
entryName
|
|
671
|
-
} = route;
|
|
672
|
-
|
|
573
|
+
} = route;
|
|
574
|
+
// check entryName, avoid matched '/' route
|
|
673
575
|
if (entryName === status.toString() || entryName === '_error') {
|
|
674
576
|
try {
|
|
675
577
|
const file = await this.routeRenderHandler({
|
|
@@ -677,22 +579,18 @@ class ModernServer {
|
|
|
677
579
|
ctx: context,
|
|
678
580
|
runner: this.runner
|
|
679
581
|
});
|
|
680
|
-
|
|
681
582
|
if (file) {
|
|
682
583
|
context.res.end(file.content);
|
|
683
584
|
return;
|
|
684
585
|
}
|
|
685
|
-
} catch (e) {
|
|
586
|
+
} catch (e) {
|
|
587
|
+
// just catch error when the rendering error occurred in the custom error page.
|
|
686
588
|
}
|
|
687
589
|
}
|
|
688
590
|
}
|
|
689
|
-
|
|
690
591
|
const text = _constants.ERROR_PAGE_TEXT[status] || _constants.ERROR_PAGE_TEXT[500];
|
|
691
592
|
context.res.end((0, _utils2.createErrorDocument)(status, text));
|
|
692
593
|
}
|
|
693
|
-
|
|
694
594
|
}
|
|
695
595
|
/* eslint-enable max-lines */
|
|
696
|
-
|
|
697
|
-
|
|
698
596
|
exports.ModernServer = ModernServer;
|