@modern-js/prod-server 2.31.2 → 2.32.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 +38 -0
- package/LICENSE +1 -1
- package/dist/cjs/constants.js +10 -0
- package/dist/cjs/libs/context/context.js +7 -2
- package/dist/cjs/libs/preload/flushServerHeader.js +67 -0
- package/dist/cjs/libs/preload/index.js +7 -0
- package/dist/cjs/libs/preload/parseLinks.js +100 -0
- package/dist/cjs/libs/preload/transformLinks2String.js +113 -0
- package/dist/cjs/libs/proxy.js +44 -41
- package/dist/cjs/libs/render/index.js +16 -2
- package/dist/cjs/libs/serverTiming.js +1 -1
- package/dist/cjs/server/modernServer.js +21 -16
- package/dist/esm/constants.js +7 -0
- package/dist/esm/libs/context/context.js +5 -2
- package/dist/esm/libs/preload/flushServerHeader.js +70 -0
- package/dist/esm/libs/preload/index.js +2 -0
- package/dist/esm/libs/preload/parseLinks.js +170 -0
- package/dist/esm/libs/preload/transformLinks2String.js +118 -0
- package/dist/esm/libs/proxy.js +88 -50
- package/dist/esm/libs/render/index.js +17 -3
- package/dist/esm/libs/serverTiming.js +1 -1
- package/dist/esm/renderHtml.js +6 -6
- package/dist/esm/server/modernServer.js +22 -17
- package/dist/esm/server/modernServerSplit.js +6 -6
- package/dist/esm-node/constants.js +7 -0
- package/dist/esm-node/libs/context/context.js +7 -2
- package/dist/esm-node/libs/preload/flushServerHeader.js +45 -0
- package/dist/esm-node/libs/preload/index.js +2 -0
- package/dist/esm-node/libs/preload/parseLinks.js +88 -0
- package/dist/esm-node/libs/preload/transformLinks2String.js +103 -0
- package/dist/esm-node/libs/proxy.js +44 -41
- package/dist/esm-node/libs/render/index.js +16 -2
- package/dist/esm-node/libs/serverTiming.js +1 -1
- package/dist/esm-node/server/modernServer.js +22 -17
- package/dist/types/constants.d.ts +7 -1
- package/dist/types/libs/context/context.d.ts +1 -1
- package/dist/types/libs/preload/flushServerHeader.d.ts +20 -0
- package/dist/types/libs/preload/index.d.ts +2 -0
- package/dist/types/libs/preload/parseLinks.d.ts +14 -0
- package/dist/types/libs/preload/transformLinks2String.d.ts +3 -0
- package/dist/types/libs/proxy.d.ts +3 -3
- package/dist/types/libs/render/index.d.ts +2 -0
- package/dist/types/libs/serverTiming.d.ts +1 -0
- package/dist/types/type.d.ts +3 -0
- package/dist/types/utils.d.ts +1 -1
- package/package.json +18 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @modern-js/prod-server
|
|
2
2
|
|
|
3
|
+
## 2.32.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @modern-js/server-core@2.32.1
|
|
8
|
+
- @modern-js/utils@2.32.1
|
|
9
|
+
- @modern-js/plugin@2.32.1
|
|
10
|
+
|
|
11
|
+
## 2.32.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- 2447d64: feat: support ssr resources preload
|
|
16
|
+
feat: 支持 ssr 资源预加载
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- e6c7d33: fix about server timing not use metaName at some case
|
|
21
|
+
- 6076166: fix: packaging errors found by publint
|
|
22
|
+
|
|
23
|
+
fix: 修复 publint 检测到的 packaging 问题
|
|
24
|
+
|
|
25
|
+
- 5f7c714: fix: WebSocket upgrade handler cause HMR connection issue
|
|
26
|
+
fix: WebSocket upgrade handler 导致 HMR 连接错误
|
|
27
|
+
- 6d73519: fix: update server reportTimings name
|
|
28
|
+
fix: 更新 server reportTimings 名称
|
|
29
|
+
- 79658a0: fix: collects ServerReportTiming Names, and then reports it only when cost != 0
|
|
30
|
+
fix: 收集 ServerReportTiming Names, 然后只有在 cost !=0 时才报告它
|
|
31
|
+
- Updated dependencies [e5a3fb4]
|
|
32
|
+
- Updated dependencies [6076166]
|
|
33
|
+
- Updated dependencies [a030aff]
|
|
34
|
+
- Updated dependencies [3c91100]
|
|
35
|
+
- Updated dependencies [2447d64]
|
|
36
|
+
- Updated dependencies [5255eba]
|
|
37
|
+
- @modern-js/utils@2.32.0
|
|
38
|
+
- @modern-js/plugin@2.32.0
|
|
39
|
+
- @modern-js/server-core@2.32.0
|
|
40
|
+
|
|
3
41
|
## 2.31.2
|
|
4
42
|
|
|
5
43
|
### Patch Changes
|
package/LICENSE
CHANGED
package/dist/cjs/constants.js
CHANGED
|
@@ -13,6 +13,9 @@ _export(exports, {
|
|
|
13
13
|
ApiServerMode: function() {
|
|
14
14
|
return ApiServerMode;
|
|
15
15
|
},
|
|
16
|
+
ServerReportTimings: function() {
|
|
17
|
+
return ServerReportTimings;
|
|
18
|
+
},
|
|
16
19
|
AGGRED_DIR: function() {
|
|
17
20
|
return AGGRED_DIR;
|
|
18
21
|
},
|
|
@@ -54,3 +57,10 @@ const RUN_MODE = {
|
|
|
54
57
|
FULL: "full",
|
|
55
58
|
TYPE: "type"
|
|
56
59
|
};
|
|
60
|
+
var ServerReportTimings;
|
|
61
|
+
(function(ServerReportTimings2) {
|
|
62
|
+
ServerReportTimings2["SERVER_HANDLE_REQUEST"] = "server-handle-request";
|
|
63
|
+
ServerReportTimings2["SERVER_MIDDLEWARE"] = "server-middleware";
|
|
64
|
+
ServerReportTimings2["SERVER_HOOK_AFTER_RENDER"] = "server-hook-after-render";
|
|
65
|
+
ServerReportTimings2["SERVER_HOOK_AFTER_MATCH"] = "server-hook-after-match";
|
|
66
|
+
})(ServerReportTimings || (ServerReportTimings = {}));
|
|
@@ -38,7 +38,12 @@ class ModernServerContext {
|
|
|
38
38
|
bind() {
|
|
39
39
|
const { req, res } = this;
|
|
40
40
|
req.get = (key) => this.getReqHeader(key);
|
|
41
|
-
res.set = (key, value) =>
|
|
41
|
+
res.set = (key, value) => {
|
|
42
|
+
if (!res.headersSent) {
|
|
43
|
+
res.setHeader(key, value);
|
|
44
|
+
}
|
|
45
|
+
return res;
|
|
46
|
+
};
|
|
42
47
|
res.send = (body) => {
|
|
43
48
|
this.send(body);
|
|
44
49
|
};
|
|
@@ -178,7 +183,7 @@ class ModernServerContext {
|
|
|
178
183
|
this.req = req;
|
|
179
184
|
this.res = res;
|
|
180
185
|
this.options = options || {};
|
|
181
|
-
this.serverTiming = new _serverTiming.ServerTiming(res, (0, _utils.cutNameByHyphen)(((_options = options) === null || _options === void 0 ? void 0 : _options.metaName) || "modern-js"));
|
|
182
186
|
this.bind();
|
|
187
|
+
this.serverTiming = new _serverTiming.ServerTiming(this.res, (0, _utils.cutNameByHyphen)(((_options = options) === null || _options === void 0 ? void 0 : _options.metaName) || "modern-js"));
|
|
183
188
|
}
|
|
184
189
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
Object.defineProperty(target, name, {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: all[name]
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
_export(exports, {
|
|
13
|
+
transformToRegExp: function() {
|
|
14
|
+
return transformToRegExp;
|
|
15
|
+
},
|
|
16
|
+
shouldFlushServerHeader: function() {
|
|
17
|
+
return shouldFlushServerHeader;
|
|
18
|
+
},
|
|
19
|
+
flushServerHeader: function() {
|
|
20
|
+
return flushServerHeader;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const _parseLinks = require("./parseLinks");
|
|
24
|
+
const _transformLinks2String = require("./transformLinks2String");
|
|
25
|
+
function transformToRegExp(input) {
|
|
26
|
+
if (typeof input === "string") {
|
|
27
|
+
return new RegExp(input);
|
|
28
|
+
}
|
|
29
|
+
return input;
|
|
30
|
+
}
|
|
31
|
+
function shouldFlushServerHeader(serverConf, userAgent, disablePreload) {
|
|
32
|
+
const { ssr: ssrConf } = serverConf || {};
|
|
33
|
+
if (disablePreload) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (typeof ssrConf === "object" && ssrConf.preload) {
|
|
37
|
+
if (typeof ssrConf.preload === "object") {
|
|
38
|
+
const { userAgentFilter } = ssrConf.preload;
|
|
39
|
+
if (userAgentFilter && userAgent) {
|
|
40
|
+
return !transformToRegExp(userAgentFilter).test(userAgent);
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
async function flushServerHeader({ serverConf, ctx, distDir, template, headers }) {
|
|
49
|
+
const { ssr: ssrConf } = serverConf || {};
|
|
50
|
+
if (typeof ssrConf !== "object") {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const { res } = ctx;
|
|
54
|
+
const links = await (0, _parseLinks.parseLinks)({
|
|
55
|
+
template,
|
|
56
|
+
distDir,
|
|
57
|
+
pathname: ctx.path
|
|
58
|
+
});
|
|
59
|
+
const link = (0, _transformLinks2String.transformLinks2String)(links, ssrConf.preload);
|
|
60
|
+
res.set("link", link);
|
|
61
|
+
for (const key in headers || {}) {
|
|
62
|
+
var _headers;
|
|
63
|
+
const value = (_headers = headers) === null || _headers === void 0 ? void 0 : _headers[key];
|
|
64
|
+
value && res.set(key, value);
|
|
65
|
+
}
|
|
66
|
+
res.flushHeaders();
|
|
67
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "parseLinks", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return parseLinks;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _interop_require_default = require("@swc/helpers/_/_interop_require_default");
|
|
12
|
+
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
|
13
|
+
const _path = /* @__PURE__ */ _interop_require_default._(require("path"));
|
|
14
|
+
const _utils = require("@modern-js/utils");
|
|
15
|
+
const _nodehtmlparser = require("node-html-parser");
|
|
16
|
+
const _remixrouter = require("@modern-js/utils/runtime/remix-router");
|
|
17
|
+
const _runtimenode = require("@modern-js/utils/runtime-node");
|
|
18
|
+
async function parseLinks({ pathname, distDir, template }) {
|
|
19
|
+
const links = await parseLinksFromRoutes(pathname, distDir);
|
|
20
|
+
return links.length > 0 ? links : parseLinksFromHtml(template);
|
|
21
|
+
}
|
|
22
|
+
function parseLinksFromHtml(html) {
|
|
23
|
+
const root = (0, _nodehtmlparser.parse)(html);
|
|
24
|
+
const scripts = root.querySelectorAll("script").filter((elem) => Boolean(elem.getAttribute("src")));
|
|
25
|
+
const css = root.querySelectorAll("link").filter((elem) => {
|
|
26
|
+
const href = elem.getAttribute("href");
|
|
27
|
+
const rel = elem.getAttribute("rel");
|
|
28
|
+
return href && rel === "stylesheet";
|
|
29
|
+
});
|
|
30
|
+
const images = root.querySelectorAll("img").filter((elem) => Boolean(elem.getAttribute("src")));
|
|
31
|
+
return scripts.map((elem) => {
|
|
32
|
+
const src = elem.getAttribute("src");
|
|
33
|
+
return {
|
|
34
|
+
uri: src,
|
|
35
|
+
as: "script"
|
|
36
|
+
};
|
|
37
|
+
}).concat(css.map((elem) => {
|
|
38
|
+
const href = elem.getAttribute("href");
|
|
39
|
+
return {
|
|
40
|
+
uri: href,
|
|
41
|
+
as: "style"
|
|
42
|
+
};
|
|
43
|
+
})).concat(images.map((elem) => {
|
|
44
|
+
const src = elem.getAttribute("src");
|
|
45
|
+
return {
|
|
46
|
+
uri: src,
|
|
47
|
+
as: "image"
|
|
48
|
+
};
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
async function parseLinksFromRoutes(pathname, distDir) {
|
|
52
|
+
const noopLinks = [];
|
|
53
|
+
const nestedRoutesSpec = _path.default.join(distDir, _utils.NESTED_ROUTE_SPEC_FILE);
|
|
54
|
+
const routesJsonPath = _path.default.join(distDir, _utils.ROUTE_SPEC_FILE);
|
|
55
|
+
const routeManifestPath = _path.default.join(distDir, _utils.ROUTE_MANIFEST_FILE);
|
|
56
|
+
if (!_utils.fs.existsSync(nestedRoutesSpec) || !_utils.fs.existsSync(routesJsonPath) || !_utils.fs.existsSync(routeManifestPath)) {
|
|
57
|
+
return noopLinks;
|
|
58
|
+
}
|
|
59
|
+
const routesJson = await Promise.resolve(routesJsonPath).then((p) => /* @__PURE__ */ _interop_require_wildcard._(require(p)));
|
|
60
|
+
const serverRoutes = routesJson.routes;
|
|
61
|
+
const entry = (0, _runtimenode.matchEntry)(pathname, serverRoutes);
|
|
62
|
+
if (entry) {
|
|
63
|
+
var _routeAssets_entryName, _matches, _assets_filter, _assets, _assets_filter1, _assets1;
|
|
64
|
+
const routes = await Promise.resolve(nestedRoutesSpec).then((p) => /* @__PURE__ */ _interop_require_wildcard._(require(p)));
|
|
65
|
+
const { entryName } = entry;
|
|
66
|
+
if (!entryName) {
|
|
67
|
+
return noopLinks;
|
|
68
|
+
}
|
|
69
|
+
const entryRoutes = routes[entryName];
|
|
70
|
+
if (!entryRoutes) {
|
|
71
|
+
return noopLinks;
|
|
72
|
+
}
|
|
73
|
+
const routesManifest = await Promise.resolve(routeManifestPath).then((p) => /* @__PURE__ */ _interop_require_wildcard._(require(p)));
|
|
74
|
+
const { routeAssets } = routesManifest;
|
|
75
|
+
const matches = (0, _remixrouter.matchRoutes)(entryRoutes, pathname, entry.urlPath);
|
|
76
|
+
const entryAssets = (_routeAssets_entryName = routeAssets[entryName]) === null || _routeAssets_entryName === void 0 ? void 0 : _routeAssets_entryName.assets;
|
|
77
|
+
const assets = (_matches = matches) === null || _matches === void 0 ? void 0 : _matches.reduce((acc, match) => {
|
|
78
|
+
const routeId = match.route.id;
|
|
79
|
+
if (routeId) {
|
|
80
|
+
var _matchedManifest;
|
|
81
|
+
const matchedManifest = routeAssets[routeId];
|
|
82
|
+
const assets2 = (_matchedManifest = matchedManifest) === null || _matchedManifest === void 0 ? void 0 : _matchedManifest.assets;
|
|
83
|
+
if (Array.isArray(assets2)) {
|
|
84
|
+
acc.push(...assets2);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return acc;
|
|
88
|
+
}, []).concat(entryAssets || []);
|
|
89
|
+
const cssLinks = (_assets = assets) === null || _assets === void 0 ? void 0 : (_assets_filter = _assets.filter((asset) => asset.endsWith(".css"))) === null || _assets_filter === void 0 ? void 0 : _assets_filter.map((uri) => ({
|
|
90
|
+
uri,
|
|
91
|
+
as: "style"
|
|
92
|
+
}));
|
|
93
|
+
const scriptLinks = (_assets1 = assets) === null || _assets1 === void 0 ? void 0 : (_assets_filter1 = _assets1.filter((asset) => asset.endsWith(".js"))) === null || _assets_filter1 === void 0 ? void 0 : _assets_filter1.map((uri) => ({
|
|
94
|
+
uri,
|
|
95
|
+
as: "script"
|
|
96
|
+
}));
|
|
97
|
+
return (cssLinks || []).concat(scriptLinks || []);
|
|
98
|
+
}
|
|
99
|
+
return noopLinks;
|
|
100
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "transformLinks2String", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return transformLinks2String;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _flushServerHeader = require("./flushServerHeader");
|
|
12
|
+
function transformLinks2String(links, preload) {
|
|
13
|
+
if (typeof preload === "boolean") {
|
|
14
|
+
return links.map(({ uri, as }) => as ? `<${uri}>; rel=preload; as=${as}` : `<${uri}>; rel=preload`).join(", ");
|
|
15
|
+
}
|
|
16
|
+
const { include, exclude, attributes } = preload;
|
|
17
|
+
const resolveLinks = addAttributes(removeExclude(addInclude(links, include), exclude), attributes);
|
|
18
|
+
return resolveLinks.join(", ");
|
|
19
|
+
function addInclude(links2, include2) {
|
|
20
|
+
var _include;
|
|
21
|
+
const images = [
|
|
22
|
+
"gif",
|
|
23
|
+
"jpg",
|
|
24
|
+
"jpeg",
|
|
25
|
+
"png",
|
|
26
|
+
"webp",
|
|
27
|
+
"bmp",
|
|
28
|
+
"tiff",
|
|
29
|
+
"anpg",
|
|
30
|
+
"ico"
|
|
31
|
+
];
|
|
32
|
+
const videos = [
|
|
33
|
+
"mp4",
|
|
34
|
+
"webm",
|
|
35
|
+
"ogm",
|
|
36
|
+
"ogv",
|
|
37
|
+
"ogg"
|
|
38
|
+
];
|
|
39
|
+
const fonts = [
|
|
40
|
+
"woff",
|
|
41
|
+
"woff2",
|
|
42
|
+
"eot",
|
|
43
|
+
"ttf",
|
|
44
|
+
"otf"
|
|
45
|
+
];
|
|
46
|
+
const includes = ((_include = include2) === null || _include === void 0 ? void 0 : _include.map((item) => {
|
|
47
|
+
if (typeof item === "string") {
|
|
48
|
+
const type = (() => {
|
|
49
|
+
if (item.endsWith(".js")) {
|
|
50
|
+
return "script";
|
|
51
|
+
}
|
|
52
|
+
if (item.endsWith(".css")) {
|
|
53
|
+
return "style";
|
|
54
|
+
}
|
|
55
|
+
if (images.some((image) => item.endsWith(`.${image}`))) {
|
|
56
|
+
return "image";
|
|
57
|
+
}
|
|
58
|
+
if (videos.some((video) => item.endsWith(`.${video}`))) {
|
|
59
|
+
return "video";
|
|
60
|
+
}
|
|
61
|
+
if (fonts.some((font) => item.endsWith(`.${font}`))) {
|
|
62
|
+
return "font";
|
|
63
|
+
}
|
|
64
|
+
})();
|
|
65
|
+
return {
|
|
66
|
+
uri: item,
|
|
67
|
+
as: type
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
uri: item.url,
|
|
72
|
+
as: item.type
|
|
73
|
+
};
|
|
74
|
+
})) || [];
|
|
75
|
+
return links2.concat(includes);
|
|
76
|
+
}
|
|
77
|
+
function removeExclude(links2, exclude2) {
|
|
78
|
+
return exclude2 ? links2.filter(({ uri }) => !(0, _flushServerHeader.transformToRegExp)(exclude2).test(uri)) : links2;
|
|
79
|
+
}
|
|
80
|
+
function addAttributes(links2, attributes2) {
|
|
81
|
+
const parseAttributes = (_attributes) => {
|
|
82
|
+
return Object.entries(_attributes || {}).reduce((results, [key, value]) => {
|
|
83
|
+
if (typeof value === "boolean") {
|
|
84
|
+
value && results.push(`; ${key}`);
|
|
85
|
+
return results;
|
|
86
|
+
}
|
|
87
|
+
results.push(`; ${key}=${value}`);
|
|
88
|
+
return results;
|
|
89
|
+
}, []).join("");
|
|
90
|
+
};
|
|
91
|
+
return links2.map(({ uri, as }) => {
|
|
92
|
+
if (as) {
|
|
93
|
+
const attributesStr = (() => {
|
|
94
|
+
const { style, script, image, font } = attributes2 || {};
|
|
95
|
+
switch (as) {
|
|
96
|
+
case "script":
|
|
97
|
+
return parseAttributes(script);
|
|
98
|
+
case "style":
|
|
99
|
+
return parseAttributes(style);
|
|
100
|
+
case "image":
|
|
101
|
+
return parseAttributes(image);
|
|
102
|
+
case "font":
|
|
103
|
+
return parseAttributes(font);
|
|
104
|
+
default:
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
107
|
+
})();
|
|
108
|
+
return `<${uri}>; rel=preload; as=${as}${attributesStr}`;
|
|
109
|
+
}
|
|
110
|
+
return `<${uri}>; rel=preload`;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
package/dist/cjs/libs/proxy.js
CHANGED
|
@@ -17,55 +17,49 @@ _export(exports, {
|
|
|
17
17
|
return createProxyHandler;
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
|
-
const _httpproxymiddleware = require("http-proxy-middleware");
|
|
20
|
+
const _httpproxymiddleware = require("http-proxy-middleware/dist/http-proxy-middleware");
|
|
21
21
|
const _utils = require("../utils");
|
|
22
22
|
function formatProxyOptions(proxyOptions) {
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Array.prototype.push.apply(formattedProxy, Object.keys(proxyOptions).reduce((total, source) => {
|
|
29
|
-
const option = proxyOptions[source];
|
|
30
|
-
total.push({
|
|
31
|
-
context: source,
|
|
32
|
-
changeOrigin: true,
|
|
33
|
-
logLevel: "warn",
|
|
34
|
-
...typeof option === "string" ? {
|
|
35
|
-
target: option
|
|
36
|
-
} : option
|
|
37
|
-
});
|
|
38
|
-
return total;
|
|
39
|
-
}, []));
|
|
40
|
-
}
|
|
23
|
+
const ret = [];
|
|
24
|
+
if (Array.isArray(proxyOptions)) {
|
|
25
|
+
ret.push(...proxyOptions);
|
|
26
|
+
} else if ("target" in proxyOptions) {
|
|
27
|
+
ret.push(proxyOptions);
|
|
41
28
|
} else {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (typeof middleware.upgrade === "function") {
|
|
53
|
-
middleware.upgrade(req, socket, head);
|
|
29
|
+
for (const [context, options] of Object.entries(proxyOptions)) {
|
|
30
|
+
const opts = {
|
|
31
|
+
context,
|
|
32
|
+
changeOrigin: true,
|
|
33
|
+
logLevel: "warn"
|
|
34
|
+
};
|
|
35
|
+
if (typeof options === "string") {
|
|
36
|
+
opts.target = options;
|
|
37
|
+
} else {
|
|
38
|
+
Object.assign(opts, options);
|
|
54
39
|
}
|
|
40
|
+
ret.push(opts);
|
|
55
41
|
}
|
|
42
|
+
}
|
|
43
|
+
const handleError = (err, _req, _res, _target) => {
|
|
44
|
+
console.error(err);
|
|
56
45
|
};
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
};
|
|
46
|
+
for (const opts of ret) {
|
|
47
|
+
var _opts;
|
|
48
|
+
var _onError;
|
|
49
|
+
(_onError = (_opts = opts).onError) !== null && _onError !== void 0 ? _onError : _opts.onError = handleError;
|
|
62
50
|
}
|
|
51
|
+
return ret;
|
|
52
|
+
}
|
|
53
|
+
const createProxyHandler = (proxyOptions) => {
|
|
54
|
+
(0, _utils.debug)("createProxyHandler", proxyOptions);
|
|
63
55
|
const formattedOptionsList = formatProxyOptions(proxyOptions);
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
const proxies = [];
|
|
57
|
+
const handlers = [];
|
|
58
|
+
for (const opts of formattedOptionsList) {
|
|
59
|
+
const proxy = new _httpproxymiddleware.HttpProxyMiddleware(opts.context, opts);
|
|
66
60
|
const handler = async (ctx, next) => {
|
|
67
61
|
const { req, res } = ctx;
|
|
68
|
-
const bypassUrl = typeof
|
|
62
|
+
const bypassUrl = typeof opts.bypass === "function" ? opts.bypass(req, res, opts) : null;
|
|
69
63
|
if (typeof bypassUrl === "boolean") {
|
|
70
64
|
ctx.status = 404;
|
|
71
65
|
next();
|
|
@@ -73,12 +67,21 @@ const createProxyHandler = (proxyOptions) => {
|
|
|
73
67
|
ctx.url = bypassUrl;
|
|
74
68
|
next();
|
|
75
69
|
} else {
|
|
76
|
-
middleware(req, res, next);
|
|
70
|
+
proxy.middleware(req, res, next);
|
|
77
71
|
}
|
|
78
72
|
};
|
|
79
|
-
|
|
73
|
+
proxies.push(proxy);
|
|
80
74
|
handlers.push(handler);
|
|
81
75
|
}
|
|
76
|
+
const handleUpgrade = (server) => {
|
|
77
|
+
for (const proxy of proxies) {
|
|
78
|
+
const raw = proxy;
|
|
79
|
+
if (raw.proxyOptions.ws === true && !raw.wsInternalSubscribed) {
|
|
80
|
+
server.on("upgrade", raw.handleUpgrade);
|
|
81
|
+
raw.wsInternalSubscribed = true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
82
85
|
return {
|
|
83
86
|
handlers,
|
|
84
87
|
handleUpgrade
|
|
@@ -13,11 +13,12 @@ const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildc
|
|
|
13
13
|
const _path = /* @__PURE__ */ _interop_require_default._(require("path"));
|
|
14
14
|
const _utils = require("@modern-js/utils");
|
|
15
15
|
const _constants = require("../../constants");
|
|
16
|
+
const _preload = require("../preload");
|
|
16
17
|
const _static = require("./static");
|
|
17
18
|
const _reader = require("./reader");
|
|
18
19
|
const _ssr = /* @__PURE__ */ _interop_require_wildcard._(require("./ssr"));
|
|
19
20
|
const _utils1 = require("./utils");
|
|
20
|
-
const createRenderHandler = ({ distDir, staticGenerate, forceCSR, nonce, ssrRender, metaName = "modern-js" }) => async function render({ ctx, route, runner }) {
|
|
21
|
+
const createRenderHandler = ({ distDir, staticGenerate, conf, forceCSR, nonce, ssrRender, metaName = "modern-js" }) => async function render({ ctx, route, runner }) {
|
|
21
22
|
if (ctx.resHasHandled()) {
|
|
22
23
|
return null;
|
|
23
24
|
}
|
|
@@ -35,6 +36,19 @@ const createRenderHandler = ({ distDir, staticGenerate, forceCSR, nonce, ssrRend
|
|
|
35
36
|
const useCSR = forceCSR && (ctx.query.csr || ctx.headers[`x-${(0, _utils.cutNameByHyphen)(metaName)}-ssr-fallback`]);
|
|
36
37
|
if (route.isSSR && !useCSR) {
|
|
37
38
|
try {
|
|
39
|
+
const userAgent = ctx.getReqHeader("User-Agent");
|
|
40
|
+
const disablePreload = Boolean(ctx.headers[`x-${(0, _utils.cutNameByHyphen)(metaName)}-disable-preload`]);
|
|
41
|
+
if ((0, _preload.shouldFlushServerHeader)(conf.server, userAgent, disablePreload)) {
|
|
42
|
+
(0, _preload.flushServerHeader)({
|
|
43
|
+
serverConf: conf.server,
|
|
44
|
+
ctx,
|
|
45
|
+
distDir,
|
|
46
|
+
template: content.toString(),
|
|
47
|
+
headers: {
|
|
48
|
+
"Content-Type": _utils.mime.contentType(_path.default.extname(templatePath))
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
38
52
|
const ssrRenderOptions = {
|
|
39
53
|
distDir,
|
|
40
54
|
entryName: route.entryName,
|
|
@@ -56,7 +70,7 @@ const createRenderHandler = ({ distDir, staticGenerate, forceCSR, nonce, ssrRend
|
|
|
56
70
|
return result;
|
|
57
71
|
} catch (err) {
|
|
58
72
|
ctx.error(_constants.ERROR_DIGEST.ERENDER, err.stack || err.message);
|
|
59
|
-
ctx.res.
|
|
73
|
+
ctx.res.set("x-modern-ssr-fallback", "1");
|
|
60
74
|
}
|
|
61
75
|
}
|
|
62
76
|
return {
|
|
@@ -15,7 +15,7 @@ class ServerTiming {
|
|
|
15
15
|
const _name = `bd-${this.meta}-${name}`;
|
|
16
16
|
const serverTiming = this.res.getHeader(SERVER_TIMING) || this.res.getHeader(SERVER_TIMING.toLocaleLowerCase());
|
|
17
17
|
const value = `${_name};${desc ? `decs="${desc}";` : ""} dur=${dur}`;
|
|
18
|
-
this.res.
|
|
18
|
+
this.res.set(SERVER_TIMING, serverTiming ? `${serverTiming}, ${value}` : value);
|
|
19
19
|
return this;
|
|
20
20
|
}
|
|
21
21
|
constructor(res, meta) {
|
|
@@ -28,17 +28,19 @@ const SERVER_DIR = "./server";
|
|
|
28
28
|
class ModernServer {
|
|
29
29
|
// server prepare
|
|
30
30
|
async onInit(runner, app) {
|
|
31
|
-
var _conf_bff, _app,
|
|
31
|
+
var _conf_bff, _app, _this_conf_output;
|
|
32
32
|
this.runner = runner;
|
|
33
33
|
const { distDir, conf } = this;
|
|
34
34
|
this.initReader();
|
|
35
35
|
(0, _utils1.debug)("final server conf", this.conf);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
if ((_conf_bff = conf.bff) === null || _conf_bff === void 0 ? void 0 : _conf_bff.proxy) {
|
|
37
|
+
const { handlers, handleUpgrade } = (0, _proxy.createProxyHandler)(conf.bff.proxy);
|
|
38
|
+
app && handleUpgrade(app);
|
|
39
|
+
handlers.forEach((handler) => {
|
|
40
|
+
this.addHandler(handler);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
(_app = app) === null || _app === void 0 ? void 0 : _app.on("close", () => {
|
|
42
44
|
this.reader.close();
|
|
43
45
|
});
|
|
44
46
|
const usageRoutes = this.filterRoutes(this.getRoutes());
|
|
@@ -62,6 +64,7 @@ class ModernServer {
|
|
|
62
64
|
distDir,
|
|
63
65
|
staticGenerate,
|
|
64
66
|
forceCSR,
|
|
67
|
+
conf: this.conf,
|
|
65
68
|
nonce: (_conf_security = conf.security) === null || _conf_security === void 0 ? void 0 : _conf_security.nonce,
|
|
66
69
|
metaName
|
|
67
70
|
});
|
|
@@ -256,7 +259,7 @@ class ModernServer {
|
|
|
256
259
|
if (this.isSend(res)) {
|
|
257
260
|
return null;
|
|
258
261
|
}
|
|
259
|
-
res.
|
|
262
|
+
res.set("content-type", renderResult.contentType);
|
|
260
263
|
return renderResult;
|
|
261
264
|
}
|
|
262
265
|
async proxy() {
|
|
@@ -291,7 +294,7 @@ class ModernServer {
|
|
|
291
294
|
const end = (0, _time.time)();
|
|
292
295
|
res.on("finish", () => {
|
|
293
296
|
const cost = end();
|
|
294
|
-
reporter.reportTiming(
|
|
297
|
+
reporter.reportTiming(_constants.ServerReportTimings.SERVER_HANDLE_REQUEST, cost);
|
|
295
298
|
});
|
|
296
299
|
let route = matched.generate(context.url);
|
|
297
300
|
if (route.isApi) {
|
|
@@ -306,7 +309,7 @@ class ModernServer {
|
|
|
306
309
|
onLast: _utils1.noop
|
|
307
310
|
});
|
|
308
311
|
const cost = end2();
|
|
309
|
-
reporter.reportTiming(
|
|
312
|
+
cost && reporter.reportTiming(_constants.ServerReportTimings.SERVER_HOOK_AFTER_MATCH, cost);
|
|
310
313
|
}
|
|
311
314
|
if (this.isSend(res)) {
|
|
312
315
|
return;
|
|
@@ -331,7 +334,7 @@ class ModernServer {
|
|
|
331
334
|
const end2 = (0, _time.time)();
|
|
332
335
|
await this.frameWebHandler(middlewareContext);
|
|
333
336
|
const cost = end2();
|
|
334
|
-
reporter.reportTiming(
|
|
337
|
+
cost && reporter.reportTiming(_constants.ServerReportTimings.SERVER_MIDDLEWARE, cost);
|
|
335
338
|
res.locals = {
|
|
336
339
|
...res.locals,
|
|
337
340
|
...middlewareContext.response.locals
|
|
@@ -358,7 +361,7 @@ class ModernServer {
|
|
|
358
361
|
onLast: _utils1.noop
|
|
359
362
|
});
|
|
360
363
|
const cost = end2();
|
|
361
|
-
reporter.reportTiming(
|
|
364
|
+
cost && reporter.reportTiming(_constants.ServerReportTimings.SERVER_HOOK_AFTER_RENDER, cost);
|
|
362
365
|
}
|
|
363
366
|
if (this.isSend(res)) {
|
|
364
367
|
return;
|
|
@@ -368,7 +371,7 @@ class ModernServer {
|
|
|
368
371
|
res.end(response);
|
|
369
372
|
}
|
|
370
373
|
isSend(res) {
|
|
371
|
-
if (res.
|
|
374
|
+
if (res.writableEnded) {
|
|
372
375
|
return true;
|
|
373
376
|
}
|
|
374
377
|
if (res.getHeader("Location") && (0, _utils1.isRedirect)(res.statusCode)) {
|
|
@@ -420,7 +423,9 @@ class ModernServer {
|
|
|
420
423
|
req.metrics = req.metrics || this.metrics;
|
|
421
424
|
let context;
|
|
422
425
|
try {
|
|
423
|
-
context = this.createContext(req, res
|
|
426
|
+
context = this.createContext(req, res, {
|
|
427
|
+
metaName: this.metaName
|
|
428
|
+
});
|
|
424
429
|
} catch (e) {
|
|
425
430
|
this.logger.error(e);
|
|
426
431
|
res.statusCode = 500;
|
|
@@ -434,7 +439,7 @@ class ModernServer {
|
|
|
434
439
|
}
|
|
435
440
|
}
|
|
436
441
|
redirect(res, url, status = 302) {
|
|
437
|
-
res.
|
|
442
|
+
res.set("Location", url);
|
|
438
443
|
res.statusCode = status;
|
|
439
444
|
res.end();
|
|
440
445
|
}
|
|
@@ -445,7 +450,7 @@ class ModernServer {
|
|
|
445
450
|
async renderErrorPage(context, status) {
|
|
446
451
|
const { res } = context;
|
|
447
452
|
context.status = status;
|
|
448
|
-
res.
|
|
453
|
+
res.set("content-type", _utils.mime.contentType("html"));
|
|
449
454
|
const statusPage = `/${status}`;
|
|
450
455
|
const customErrorPage = `/_error`;
|
|
451
456
|
const matched = this.router.match(statusPage) || this.router.match(customErrorPage);
|
package/dist/esm/constants.js
CHANGED
|
@@ -26,3 +26,10 @@ export var RUN_MODE = {
|
|
|
26
26
|
FULL: "full",
|
|
27
27
|
TYPE: "type"
|
|
28
28
|
};
|
|
29
|
+
export var ServerReportTimings;
|
|
30
|
+
(function(ServerReportTimings2) {
|
|
31
|
+
ServerReportTimings2["SERVER_HANDLE_REQUEST"] = "server-handle-request";
|
|
32
|
+
ServerReportTimings2["SERVER_MIDDLEWARE"] = "server-middleware";
|
|
33
|
+
ServerReportTimings2["SERVER_HOOK_AFTER_RENDER"] = "server-hook-after-render";
|
|
34
|
+
ServerReportTimings2["SERVER_HOOK_AFTER_MATCH"] = "server-hook-after-match";
|
|
35
|
+
})(ServerReportTimings || (ServerReportTimings = {}));
|