@modern-js/prod-server 2.4.0 → 2.5.0
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 +27 -0
- package/dist/{js/node → cjs}/constants.js +0 -0
- package/dist/{js/node → cjs}/index.js +0 -0
- package/dist/{js/node → cjs}/libs/context/context.js +0 -0
- package/dist/{js/node → cjs}/libs/context/index.js +0 -0
- package/dist/{js/node → cjs}/libs/hook-api/index.js +12 -25
- package/dist/{js/node → cjs}/libs/hook-api/route.js +0 -0
- package/dist/{js/node → cjs}/libs/hook-api/template.js +0 -0
- package/dist/{js/node → cjs}/libs/loadConfig.js +6 -21
- package/dist/cjs/libs/logger.js +122 -0
- package/dist/{js/node → cjs}/libs/metrics.js +0 -0
- package/dist/{js/node → cjs}/libs/proxy.js +6 -39
- package/dist/{js/node → cjs}/libs/render/cache/__tests__/cache.fun.test.js +12 -34
- package/dist/{js/node → cjs}/libs/render/cache/__tests__/cache.test.js +43 -78
- package/dist/{js/node → cjs}/libs/render/cache/__tests__/cacheable.js +0 -0
- package/dist/{js/node → cjs}/libs/render/cache/__tests__/error-configuration.js +0 -0
- package/dist/{js/node → cjs}/libs/render/cache/__tests__/matched-cache.js +0 -0
- package/dist/cjs/libs/render/cache/index.js +97 -0
- package/dist/cjs/libs/render/cache/page-caches/index.js +33 -0
- package/dist/{js/node → cjs}/libs/render/cache/page-caches/lru.js +0 -0
- package/dist/{js/node → cjs}/libs/render/cache/spr.js +69 -97
- package/dist/{js/node → cjs}/libs/render/cache/type.js +0 -0
- package/dist/{js/node → cjs}/libs/render/cache/util.js +19 -41
- package/dist/cjs/libs/render/index.js +93 -0
- package/dist/{js/node → cjs}/libs/render/measure.js +6 -21
- package/dist/{js/node → cjs}/libs/render/reader.js +24 -46
- package/dist/{js/node → cjs}/libs/render/ssr.js +3 -23
- package/dist/{js/node → cjs}/libs/render/static.js +22 -44
- package/dist/{js/node → cjs}/libs/render/type.js +0 -0
- package/dist/{js/node → cjs}/libs/route/index.js +0 -0
- package/dist/{js/node → cjs}/libs/route/matcher.js +0 -0
- package/dist/{js/node → cjs}/libs/route/route.js +0 -0
- package/dist/{js/node → cjs}/libs/serve-file.js +2 -22
- package/dist/{js/node → cjs}/server/index.js +56 -106
- package/dist/{js/node → cjs}/server/modern-server-split.js +9 -40
- package/dist/cjs/server/modern-server.js +490 -0
- package/dist/{js/node → cjs}/type.js +0 -0
- package/dist/{js/node → cjs}/utils.js +1 -15
- package/dist/{js/node → cjs}/worker-server.js +51 -35
- package/dist/{js/treeshaking → esm}/constants.js +0 -0
- package/dist/{js/treeshaking → esm}/index.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/context/context.js +2 -2
- package/dist/{js/treeshaking → esm}/libs/context/index.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/hook-api/index.js +1 -1
- package/dist/{js/treeshaking → esm}/libs/hook-api/route.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/hook-api/template.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/loadConfig.js +0 -0
- package/dist/esm/libs/logger.js +205 -0
- package/dist/{js/treeshaking → esm}/libs/metrics.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/proxy.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/cache/__tests__/cache.fun.test.js +3 -3
- package/dist/{js/treeshaking → esm}/libs/render/cache/__tests__/cache.test.js +2 -2
- package/dist/{js/treeshaking → esm}/libs/render/cache/__tests__/cacheable.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/cache/__tests__/error-configuration.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/cache/__tests__/matched-cache.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/cache/index.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/cache/page-caches/index.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/cache/page-caches/lru.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/cache/spr.js +8 -8
- package/dist/{js/treeshaking → esm}/libs/render/cache/type.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/cache/util.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/index.js +4 -3
- package/dist/{js/treeshaking → esm}/libs/render/measure.js +2 -2
- package/dist/{js/treeshaking → esm}/libs/render/reader.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/ssr.js +3 -3
- package/dist/{js/treeshaking → esm}/libs/render/static.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/render/type.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/route/index.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/route/matcher.js +2 -2
- package/dist/{js/treeshaking → esm}/libs/route/route.js +0 -0
- package/dist/{js/treeshaking → esm}/libs/serve-file.js +2 -2
- package/dist/{js/treeshaking → esm}/server/index.js +3 -3
- package/dist/{js/treeshaking → esm}/server/modern-server-split.js +0 -0
- package/dist/{js/treeshaking → esm}/server/modern-server.js +21 -15
- package/dist/{js/treeshaking → esm}/type.js +0 -0
- package/dist/{js/treeshaking → esm}/utils.js +1 -1
- package/dist/{js/treeshaking → esm}/worker-server.js +64 -8
- package/dist/{js/modern → esm-node}/constants.js +0 -0
- package/dist/{js/modern → esm-node}/index.js +0 -0
- package/dist/{js/modern → esm-node}/libs/context/context.js +0 -0
- package/dist/{js/modern → esm-node}/libs/context/index.js +0 -0
- package/dist/{js/modern → esm-node}/libs/hook-api/index.js +12 -27
- package/dist/{js/modern → esm-node}/libs/hook-api/route.js +0 -0
- package/dist/{js/modern → esm-node}/libs/hook-api/template.js +0 -0
- package/dist/esm-node/libs/loadConfig.js +45 -0
- package/dist/esm-node/libs/logger.js +98 -0
- package/dist/{js/modern → esm-node}/libs/metrics.js +0 -0
- package/dist/{js/modern → esm-node}/libs/proxy.js +6 -41
- package/dist/esm-node/libs/render/cache/__tests__/cache.fun.test.js +83 -0
- package/dist/esm-node/libs/render/cache/__tests__/cache.test.js +210 -0
- package/dist/{js/modern → esm-node}/libs/render/cache/__tests__/cacheable.js +0 -0
- package/dist/{js/modern → esm-node}/libs/render/cache/__tests__/error-configuration.js +0 -0
- package/dist/{js/modern → esm-node}/libs/render/cache/__tests__/matched-cache.js +0 -0
- package/dist/esm-node/libs/render/cache/index.js +76 -0
- package/dist/esm-node/libs/render/cache/page-caches/index.js +10 -0
- package/dist/{js/modern → esm-node}/libs/render/cache/page-caches/lru.js +0 -0
- package/dist/{js/modern → esm-node}/libs/render/cache/spr.js +69 -97
- package/dist/{js/modern → esm-node}/libs/render/cache/type.js +0 -0
- package/dist/{js/modern → esm-node}/libs/render/cache/util.js +19 -41
- package/dist/esm-node/libs/render/index.js +64 -0
- package/dist/{js/modern → esm-node}/libs/render/measure.js +6 -23
- package/dist/esm-node/libs/render/reader.js +85 -0
- package/dist/{js/modern → esm-node}/libs/render/ssr.js +3 -23
- package/dist/esm-node/libs/render/static.js +38 -0
- package/dist/{js/modern → esm-node}/libs/render/type.js +0 -0
- package/dist/{js/modern → esm-node}/libs/route/index.js +0 -0
- package/dist/{js/modern → esm-node}/libs/route/matcher.js +0 -0
- package/dist/{js/modern → esm-node}/libs/route/route.js +0 -0
- package/dist/{js/modern → esm-node}/libs/serve-file.js +2 -22
- package/dist/esm-node/server/index.js +156 -0
- package/dist/esm-node/server/modern-server-split.js +43 -0
- package/dist/esm-node/server/modern-server.js +483 -0
- package/dist/{js/modern → esm-node}/type.js +0 -0
- package/dist/{js/modern → esm-node}/utils.js +1 -17
- package/dist/esm-node/worker-server.js +69 -0
- package/dist/types/libs/context/context.d.ts +1 -1
- package/dist/types/libs/logger.d.ts +63 -0
- package/dist/types/libs/render/index.d.ts +3 -1
- package/dist/types/utils.d.ts +1 -1
- package/dist/types/worker-server.d.ts +2 -1
- package/package.json +15 -16
- package/dist/js/modern/libs/loadConfig.js +0 -62
- package/dist/js/modern/libs/render/cache/__tests__/cache.fun.test.js +0 -114
- package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +0 -254
- package/dist/js/modern/libs/render/cache/index.js +0 -115
- package/dist/js/modern/libs/render/cache/page-caches/index.js +0 -32
- package/dist/js/modern/libs/render/index.js +0 -84
- package/dist/js/modern/libs/render/reader.js +0 -107
- package/dist/js/modern/libs/render/static.js +0 -60
- package/dist/js/modern/server/index.js +0 -208
- package/dist/js/modern/server/modern-server-split.js +0 -74
- package/dist/js/modern/server/modern-server.js +0 -548
- package/dist/js/modern/worker-server.js +0 -54
- package/dist/js/node/libs/render/cache/index.js +0 -134
- package/dist/js/node/libs/render/cache/page-caches/index.js +0 -55
- package/dist/js/node/libs/render/index.js +0 -113
- package/dist/js/node/server/modern-server.js +0 -553
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { createCache, destroyCache } from "../spr";
|
|
2
|
+
import { errorConfiguration } from "./error-configuration";
|
|
3
|
+
import { cacheabelAry } from "./cacheable";
|
|
4
|
+
import { matchedCacheableAry } from "./matched-cache";
|
|
5
|
+
const createCacheConfig = (config = {}) => ({
|
|
6
|
+
excludes: null,
|
|
7
|
+
includes: null,
|
|
8
|
+
interval: 10,
|
|
9
|
+
staleLimit: false,
|
|
10
|
+
level: 0,
|
|
11
|
+
fallback: false,
|
|
12
|
+
matches: null,
|
|
13
|
+
...config
|
|
14
|
+
});
|
|
15
|
+
jest.setTimeout(6e4);
|
|
16
|
+
describe("cache", () => {
|
|
17
|
+
it("should cache correctly", async () => {
|
|
18
|
+
destroyCache();
|
|
19
|
+
const cache = createCache();
|
|
20
|
+
const context = {
|
|
21
|
+
entry: "",
|
|
22
|
+
pathname: "",
|
|
23
|
+
query: {},
|
|
24
|
+
headers: {}
|
|
25
|
+
};
|
|
26
|
+
const content = "hello";
|
|
27
|
+
const cacheConfig = createCacheConfig();
|
|
28
|
+
await cache.set(context, content, cacheConfig, true);
|
|
29
|
+
const cacheResult = await cache.get(context);
|
|
30
|
+
expect(cacheResult).not.toBe(null);
|
|
31
|
+
expect(cacheResult == null ? void 0 : cacheResult.content).toBe("hello");
|
|
32
|
+
});
|
|
33
|
+
it("should ignore cache set when cache config not exist", async () => {
|
|
34
|
+
destroyCache();
|
|
35
|
+
destroyCache();
|
|
36
|
+
const cache = createCache();
|
|
37
|
+
const context = {
|
|
38
|
+
entry: "",
|
|
39
|
+
pathname: "",
|
|
40
|
+
query: {},
|
|
41
|
+
headers: {}
|
|
42
|
+
};
|
|
43
|
+
const content = "hello";
|
|
44
|
+
const shouldCache = await cache.set(context, content, null, true);
|
|
45
|
+
expect(shouldCache).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
it("should calcual cache key error", async () => {
|
|
48
|
+
destroyCache();
|
|
49
|
+
const cache = createCache();
|
|
50
|
+
const content = "hello";
|
|
51
|
+
for (const config of errorConfiguration) {
|
|
52
|
+
const cacheConfig = createCacheConfig(config);
|
|
53
|
+
const tmpEntry = Math.random().toString();
|
|
54
|
+
const context = {
|
|
55
|
+
entry: tmpEntry,
|
|
56
|
+
pathname: "",
|
|
57
|
+
query: {},
|
|
58
|
+
headers: {}
|
|
59
|
+
};
|
|
60
|
+
const shouldCache = await cache.set(context, content, cacheConfig);
|
|
61
|
+
expect(shouldCache).toBe(false);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
it("should get nothing for diff requestKey", async () => {
|
|
65
|
+
destroyCache();
|
|
66
|
+
const cache = createCache();
|
|
67
|
+
const context = {
|
|
68
|
+
entry: "",
|
|
69
|
+
pathname: "",
|
|
70
|
+
query: {},
|
|
71
|
+
headers: {}
|
|
72
|
+
};
|
|
73
|
+
const content = "hello";
|
|
74
|
+
const cacheConfig = createCacheConfig({
|
|
75
|
+
level: 1,
|
|
76
|
+
includes: { query: ["name"] }
|
|
77
|
+
});
|
|
78
|
+
await cache.set(context, content, cacheConfig, true);
|
|
79
|
+
const context_req = {
|
|
80
|
+
entry: "",
|
|
81
|
+
pathname: "/home",
|
|
82
|
+
query: {},
|
|
83
|
+
headers: {}
|
|
84
|
+
};
|
|
85
|
+
const cacheResult = await cache.get(context_req);
|
|
86
|
+
expect(cacheResult).toBe(null);
|
|
87
|
+
});
|
|
88
|
+
it("should get nothing for diff cacheHash", async () => {
|
|
89
|
+
destroyCache();
|
|
90
|
+
const cache = createCache();
|
|
91
|
+
const context = {
|
|
92
|
+
entry: "",
|
|
93
|
+
pathname: "",
|
|
94
|
+
query: {},
|
|
95
|
+
headers: {}
|
|
96
|
+
};
|
|
97
|
+
const content = "hello";
|
|
98
|
+
const cacheConfig = createCacheConfig({
|
|
99
|
+
level: 1,
|
|
100
|
+
includes: { query: ["name"] }
|
|
101
|
+
});
|
|
102
|
+
await cache.set(context, content, cacheConfig, true);
|
|
103
|
+
const context_req = {
|
|
104
|
+
entry: "",
|
|
105
|
+
pathname: "",
|
|
106
|
+
query: { name: "zll" },
|
|
107
|
+
headers: {}
|
|
108
|
+
};
|
|
109
|
+
const cacheResult = await cache.get(context_req);
|
|
110
|
+
expect(cacheResult).toBe(null);
|
|
111
|
+
});
|
|
112
|
+
it("should get cache correctly", async () => {
|
|
113
|
+
destroyCache();
|
|
114
|
+
const cache = createCache();
|
|
115
|
+
for (const cacheable of cacheabelAry) {
|
|
116
|
+
const context = {
|
|
117
|
+
entry: "",
|
|
118
|
+
pathname: cacheable.requestOpt.url,
|
|
119
|
+
query: cacheable.requestOpt.query || {},
|
|
120
|
+
headers: cacheable.requestOpt.headers || {}
|
|
121
|
+
};
|
|
122
|
+
const cacheConfig = createCacheConfig(cacheable.cacheConfig || {});
|
|
123
|
+
await cache.set(context, cacheable.content, cacheConfig, true);
|
|
124
|
+
const cacheResult = await cache.get(context);
|
|
125
|
+
expect(cacheResult == null ? void 0 : cacheResult.content).toBe(cacheable.content);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
it("should match cache correctly", async () => {
|
|
129
|
+
destroyCache();
|
|
130
|
+
const cache = createCache();
|
|
131
|
+
for (const cacheable of matchedCacheableAry) {
|
|
132
|
+
const [baseCacheable, matchOne, ...other] = cacheable;
|
|
133
|
+
const { requestOpt = {}, cacheConfig, content } = baseCacheable;
|
|
134
|
+
const context = {
|
|
135
|
+
entry: "",
|
|
136
|
+
pathname: requestOpt.url,
|
|
137
|
+
query: requestOpt.query,
|
|
138
|
+
headers: requestOpt.headers
|
|
139
|
+
};
|
|
140
|
+
await cache.set(context, content, createCacheConfig(cacheConfig), true);
|
|
141
|
+
const matchContext = {
|
|
142
|
+
entry: "",
|
|
143
|
+
pathname: matchOne.url,
|
|
144
|
+
query: matchOne.query,
|
|
145
|
+
headers: matchOne.headers
|
|
146
|
+
};
|
|
147
|
+
const cacheResult = await cache.get(matchContext);
|
|
148
|
+
expect(cacheResult == null ? void 0 : cacheResult.content).toBe(content);
|
|
149
|
+
for (const notMatch of other) {
|
|
150
|
+
const notMatchContext = {
|
|
151
|
+
entry: "",
|
|
152
|
+
pathname: notMatch.url,
|
|
153
|
+
query: notMatch.query,
|
|
154
|
+
headers: notMatch.headers
|
|
155
|
+
};
|
|
156
|
+
const nothing = await cache.get(notMatchContext);
|
|
157
|
+
expect(nothing).toBe(null);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
it("should stale cache correctly", async () => {
|
|
162
|
+
destroyCache();
|
|
163
|
+
const cache = createCache();
|
|
164
|
+
const context = {
|
|
165
|
+
entry: "",
|
|
166
|
+
pathname: "",
|
|
167
|
+
query: {},
|
|
168
|
+
headers: {}
|
|
169
|
+
};
|
|
170
|
+
const config = createCacheConfig({ interval: 5 });
|
|
171
|
+
const content = "hello";
|
|
172
|
+
const shouldCache = await cache.set(context, content, config, true);
|
|
173
|
+
expect(shouldCache.value).toBe(true);
|
|
174
|
+
const freshResult = await cache.get(context);
|
|
175
|
+
expect(freshResult == null ? void 0 : freshResult.isStale).toBe(false);
|
|
176
|
+
await new Promise((resolve) => {
|
|
177
|
+
setTimeout(() => {
|
|
178
|
+
resolve();
|
|
179
|
+
}, 6e3);
|
|
180
|
+
});
|
|
181
|
+
const staleResult = await cache.get(context);
|
|
182
|
+
expect(staleResult == null ? void 0 : staleResult.isStale).toBe(true);
|
|
183
|
+
});
|
|
184
|
+
it("should garbage cache correctly", async () => {
|
|
185
|
+
destroyCache();
|
|
186
|
+
const cache = createCache();
|
|
187
|
+
const context = {
|
|
188
|
+
entry: "",
|
|
189
|
+
pathname: "",
|
|
190
|
+
query: {},
|
|
191
|
+
headers: {}
|
|
192
|
+
};
|
|
193
|
+
const config = createCacheConfig({
|
|
194
|
+
interval: 3,
|
|
195
|
+
staleLimit: 8
|
|
196
|
+
});
|
|
197
|
+
const content = "hello";
|
|
198
|
+
const shouldCache = await cache.set(context, content, config, true);
|
|
199
|
+
expect(shouldCache.value).toBe(true);
|
|
200
|
+
const freshResult = await cache.get(context);
|
|
201
|
+
expect(freshResult == null ? void 0 : freshResult.isGarbage).toBe(false);
|
|
202
|
+
await new Promise((resolve) => {
|
|
203
|
+
setTimeout(() => {
|
|
204
|
+
resolve();
|
|
205
|
+
}, 1e4);
|
|
206
|
+
});
|
|
207
|
+
const staleResult = await cache.get(context);
|
|
208
|
+
expect(staleResult == null ? void 0 : staleResult.isGarbage).toBe(true);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Transform } from "stream";
|
|
2
|
+
import { ERROR_DIGEST } from "../../../constants";
|
|
3
|
+
import { createCache } from "./spr";
|
|
4
|
+
import { namespaceHash, withCoalescedInvoke } from "./util";
|
|
5
|
+
var cache_default = (renderFn, ctx) => {
|
|
6
|
+
const sprCache = createCache();
|
|
7
|
+
const doRender = async (context) => {
|
|
8
|
+
const cacheContext = {
|
|
9
|
+
entry: context.entryName,
|
|
10
|
+
...context.request
|
|
11
|
+
};
|
|
12
|
+
const cacheFile = await sprCache.get(cacheContext);
|
|
13
|
+
async function afterRender(source, onAfterRender) {
|
|
14
|
+
if (!source) {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
if (typeof source === "string") {
|
|
18
|
+
await onAfterRender(source);
|
|
19
|
+
return source;
|
|
20
|
+
} else {
|
|
21
|
+
let htmlForStream = "";
|
|
22
|
+
const cacheStream = new Transform({
|
|
23
|
+
write(chunk, _, callback) {
|
|
24
|
+
htmlForStream += chunk.toString();
|
|
25
|
+
this.push(chunk);
|
|
26
|
+
callback();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
cacheStream.on("close", () => onAfterRender(htmlForStream));
|
|
30
|
+
return source(cacheStream);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function saveHtmlIntoCache(html) {
|
|
34
|
+
const { cacheConfig } = context;
|
|
35
|
+
if (html && cacheConfig) {
|
|
36
|
+
await sprCache.set(cacheContext, html, cacheConfig);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!cacheFile) {
|
|
40
|
+
const renderResult = await renderFn(context);
|
|
41
|
+
return afterRender(renderResult, saveHtmlIntoCache);
|
|
42
|
+
}
|
|
43
|
+
const cacheHash = cacheFile == null ? void 0 : cacheFile.hash;
|
|
44
|
+
if (cacheFile.isGarbage) {
|
|
45
|
+
const renderResult = await renderFn(context);
|
|
46
|
+
return afterRender(renderResult, saveHtmlIntoCache);
|
|
47
|
+
} else if (cacheFile.isStale) {
|
|
48
|
+
const render = withCoalescedInvoke(() => renderFn(context)).bind(
|
|
49
|
+
null,
|
|
50
|
+
namespaceHash("render", cacheFile.hash),
|
|
51
|
+
[]
|
|
52
|
+
);
|
|
53
|
+
render().then(async (res) => {
|
|
54
|
+
if (res.value && res.isOrigin) {
|
|
55
|
+
const { cacheConfig } = context;
|
|
56
|
+
if (cacheConfig) {
|
|
57
|
+
afterRender(res.value, async (html) => {
|
|
58
|
+
sprCache.set(cacheContext, html, cacheConfig);
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
sprCache.del(cacheContext, cacheHash);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}).catch((e) => {
|
|
65
|
+
sprCache.del(cacheContext, cacheHash);
|
|
66
|
+
ctx.error(ERROR_DIGEST.ERENDER, e);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
ctx.res.setHeader("x-modern-spr", "1");
|
|
70
|
+
return cacheFile.content;
|
|
71
|
+
};
|
|
72
|
+
return doRender;
|
|
73
|
+
};
|
|
74
|
+
export {
|
|
75
|
+
cache_default as default
|
|
76
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LRUCaches } from "./lru";
|
|
2
|
+
async function createPageCaches(max) {
|
|
3
|
+
const constructorOptions = { max };
|
|
4
|
+
const cacheInstance = new LRUCaches(constructorOptions);
|
|
5
|
+
await cacheInstance.init();
|
|
6
|
+
return cacheInstance;
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
createPageCaches
|
|
10
|
+
};
|
|
File without changes
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
var __async = (__this, __arguments, generator) => {
|
|
2
|
-
return new Promise((resolve, reject) => {
|
|
3
|
-
var fulfilled = (value) => {
|
|
4
|
-
try {
|
|
5
|
-
step(generator.next(value));
|
|
6
|
-
} catch (e) {
|
|
7
|
-
reject(e);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
var rejected = (value) => {
|
|
11
|
-
try {
|
|
12
|
-
step(generator.throw(value));
|
|
13
|
-
} catch (e) {
|
|
14
|
-
reject(e);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
18
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
1
|
import crypto from "crypto";
|
|
22
2
|
import LRUCache from "lru-cache";
|
|
23
3
|
import { mime } from "@modern-js/utils";
|
|
@@ -138,15 +118,13 @@ class CacheManager {
|
|
|
138
118
|
const headerFactor = this.factor(headerKeys, requestHeader, headerMatches);
|
|
139
119
|
return headerFactor;
|
|
140
120
|
}
|
|
141
|
-
best(context, cacheKey, data) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
return data.caches.get(cacheHash);
|
|
149
|
-
});
|
|
121
|
+
async best(context, cacheKey, data) {
|
|
122
|
+
const { level } = data;
|
|
123
|
+
const cacheHash = this.find[fname(level)](context, cacheKey, data);
|
|
124
|
+
if (!cacheHash) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return data.caches.get(cacheHash);
|
|
150
128
|
}
|
|
151
129
|
createCacheContent(config, caches) {
|
|
152
130
|
return {
|
|
@@ -158,77 +136,71 @@ class CacheManager {
|
|
|
158
136
|
caches
|
|
159
137
|
};
|
|
160
138
|
}
|
|
161
|
-
get(context) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
};
|
|
182
|
-
});
|
|
139
|
+
async get(context) {
|
|
140
|
+
const cacheKey = this.generateRequestKey(context);
|
|
141
|
+
const data = this.cache.get(cacheKey);
|
|
142
|
+
if (!data) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const dest = await this.best(context, cacheKey, data);
|
|
146
|
+
if (!dest) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const { expireTime, limitTime, html, cacheHash } = dest;
|
|
150
|
+
const isStale = Date.now() - expireTime > 0;
|
|
151
|
+
const isGarbage = limitTime ? Date.now() - limitTime > 0 : false;
|
|
152
|
+
return {
|
|
153
|
+
content: html || "",
|
|
154
|
+
contentType: mime.contentType("html"),
|
|
155
|
+
isStale,
|
|
156
|
+
isGarbage,
|
|
157
|
+
hash: cacheHash
|
|
158
|
+
};
|
|
183
159
|
}
|
|
184
|
-
set(context, html, cacheConfig, sync = false) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
size
|
|
214
|
-
});
|
|
215
|
-
this.cache.set(cacheKey, next);
|
|
216
|
-
return true;
|
|
160
|
+
async set(context, html, cacheConfig, sync = false) {
|
|
161
|
+
if (!cacheConfig) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
const cacheKey = this.generateRequestKey(context);
|
|
165
|
+
let data = this.cache.get(cacheKey);
|
|
166
|
+
if (!data) {
|
|
167
|
+
const caches = await createPageCaches(MAX_CACHE_EACH_REQ);
|
|
168
|
+
data = this.createCacheContent(cacheConfig, caches);
|
|
169
|
+
}
|
|
170
|
+
const cacheHash = this.find[fname(cacheConfig.level)](
|
|
171
|
+
context,
|
|
172
|
+
cacheKey,
|
|
173
|
+
data
|
|
174
|
+
);
|
|
175
|
+
if (!cacheHash) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
const cacheSyncOrAsync = async () => {
|
|
179
|
+
const next = data;
|
|
180
|
+
const limit = cacheConfig.staleLimit;
|
|
181
|
+
const storeHTML = cacheAddition(html, cacheHash);
|
|
182
|
+
const size = storeHTML.length;
|
|
183
|
+
await next.caches.set(cacheHash, {
|
|
184
|
+
expireTime: Date.now() + cacheConfig.interval * 1e3,
|
|
185
|
+
limitTime: typeof limit === "number" ? Date.now() + limit * 1e3 : null,
|
|
186
|
+
cacheHash,
|
|
187
|
+
html: storeHTML,
|
|
188
|
+
size
|
|
217
189
|
});
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
190
|
+
this.cache.set(cacheKey, next);
|
|
191
|
+
return true;
|
|
192
|
+
};
|
|
193
|
+
const doCache = withCoalescedInvoke(cacheSyncOrAsync).bind(
|
|
194
|
+
null,
|
|
195
|
+
namespaceHash("stream", cacheHash),
|
|
196
|
+
[]
|
|
197
|
+
);
|
|
198
|
+
return maybeSync(doCache)(sync);
|
|
225
199
|
}
|
|
226
|
-
del(context, cacheHash) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
data == null ? void 0 : data.caches.del(cacheHash);
|
|
231
|
-
});
|
|
200
|
+
async del(context, cacheHash) {
|
|
201
|
+
const cacheKey = this.generateRequestKey(context);
|
|
202
|
+
const data = this.cache.get(cacheKey);
|
|
203
|
+
data == null ? void 0 : data.caches.del(cacheHash);
|
|
232
204
|
}
|
|
233
205
|
}
|
|
234
206
|
let manager;
|
|
File without changes
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
var __async = (__this, __arguments, generator) => {
|
|
2
|
-
return new Promise((resolve, reject) => {
|
|
3
|
-
var fulfilled = (value) => {
|
|
4
|
-
try {
|
|
5
|
-
step(generator.next(value));
|
|
6
|
-
} catch (e) {
|
|
7
|
-
reject(e);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
var rejected = (value) => {
|
|
11
|
-
try {
|
|
12
|
-
step(generator.throw(value));
|
|
13
|
-
} catch (e) {
|
|
14
|
-
reject(e);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
18
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
1
|
import url from "url";
|
|
22
2
|
function namespaceHash(namespace, hash) {
|
|
23
3
|
return `${namespace}/${hash}`;
|
|
@@ -56,28 +36,26 @@ function cacheAddition(html, hash) {
|
|
|
56
36
|
}
|
|
57
37
|
const globalInvokeCache = /* @__PURE__ */ new Map();
|
|
58
38
|
function withCoalescedInvoke(func) {
|
|
59
|
-
return function(key, args) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
throw err;
|
|
77
|
-
});
|
|
78
|
-
globalInvokeCache.set(key, future);
|
|
79
|
-
return future;
|
|
39
|
+
return async function(key, args) {
|
|
40
|
+
const entry = globalInvokeCache.get(key);
|
|
41
|
+
if (entry) {
|
|
42
|
+
return entry.then((res) => ({
|
|
43
|
+
isOrigin: false,
|
|
44
|
+
value: res.value
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
function __wrapper() {
|
|
48
|
+
return func(...args);
|
|
49
|
+
}
|
|
50
|
+
const future = __wrapper().then((res) => {
|
|
51
|
+
globalInvokeCache.delete(key);
|
|
52
|
+
return { isOrigin: true, value: res };
|
|
53
|
+
}).catch((err) => {
|
|
54
|
+
globalInvokeCache.delete(key);
|
|
55
|
+
throw err;
|
|
80
56
|
});
|
|
57
|
+
globalInvokeCache.set(key, future);
|
|
58
|
+
return future;
|
|
81
59
|
};
|
|
82
60
|
}
|
|
83
61
|
function maybeSync(fn) {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { fs, mime } from "@modern-js/utils";
|
|
3
|
+
import { ERROR_DIGEST } from "../../constants";
|
|
4
|
+
import { handleDirectory } from "./static";
|
|
5
|
+
import { readFile } from "./reader";
|
|
6
|
+
import * as ssr from "./ssr";
|
|
7
|
+
const createRenderHandler = ({
|
|
8
|
+
distDir,
|
|
9
|
+
staticGenerate,
|
|
10
|
+
forceCSR
|
|
11
|
+
}) => async function render({
|
|
12
|
+
ctx,
|
|
13
|
+
route,
|
|
14
|
+
runner
|
|
15
|
+
}) {
|
|
16
|
+
if (ctx.resHasHandled()) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const { entryPath, urlPath } = route;
|
|
20
|
+
const entry = path.join(distDir, entryPath);
|
|
21
|
+
if (!route.isSPA) {
|
|
22
|
+
const result = await handleDirectory(ctx, entry, urlPath);
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
const templatePath = entry;
|
|
26
|
+
if (!fs.existsSync(templatePath)) {
|
|
27
|
+
throw new Error(`Could not find template file: ${templatePath}`);
|
|
28
|
+
}
|
|
29
|
+
const content = await readFile(templatePath);
|
|
30
|
+
if (!content) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const useCSR = forceCSR && ctx.query.csr;
|
|
34
|
+
if (route.isSSR && !useCSR) {
|
|
35
|
+
try {
|
|
36
|
+
const result = await ssr.render(
|
|
37
|
+
ctx,
|
|
38
|
+
{
|
|
39
|
+
distDir,
|
|
40
|
+
entryName: route.entryName,
|
|
41
|
+
urlPath: route.urlPath,
|
|
42
|
+
bundle: route.bundle,
|
|
43
|
+
template: content.toString(),
|
|
44
|
+
staticGenerate
|
|
45
|
+
},
|
|
46
|
+
runner
|
|
47
|
+
);
|
|
48
|
+
return result;
|
|
49
|
+
} catch (err) {
|
|
50
|
+
ctx.error(
|
|
51
|
+
ERROR_DIGEST.ERENDER,
|
|
52
|
+
err.stack || err.message
|
|
53
|
+
);
|
|
54
|
+
ctx.res.setHeader("x-modern-ssr-fallback", "1");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
content,
|
|
59
|
+
contentType: mime.contentType(path.extname(templatePath))
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
export {
|
|
63
|
+
createRenderHandler
|
|
64
|
+
};
|
|
@@ -1,37 +1,20 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defProps = Object.defineProperties;
|
|
3
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
-
var __spreadValues = (a, b) => {
|
|
9
|
-
for (var prop in b || (b = {}))
|
|
10
|
-
if (__hasOwnProp.call(b, prop))
|
|
11
|
-
__defNormalProp(a, prop, b[prop]);
|
|
12
|
-
if (__getOwnPropSymbols)
|
|
13
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
-
if (__propIsEnum.call(b, prop))
|
|
15
|
-
__defNormalProp(a, prop, b[prop]);
|
|
16
|
-
}
|
|
17
|
-
return a;
|
|
18
|
-
};
|
|
19
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
1
|
import { headersWithoutCookie } from "../../utils";
|
|
21
2
|
const createMetrics = (context, metrics) => {
|
|
22
3
|
const { entryName: entry, request } = context;
|
|
23
4
|
const { pathname = "" } = request || {};
|
|
24
5
|
const emitTimer = (name, cost, tags = {}) => {
|
|
25
|
-
metrics.emitTimer(name, cost,
|
|
6
|
+
metrics.emitTimer(name, cost, {
|
|
7
|
+
...tags,
|
|
26
8
|
pathname,
|
|
27
9
|
entry
|
|
28
|
-
})
|
|
10
|
+
});
|
|
29
11
|
};
|
|
30
12
|
const emitCounter = (name, counter, tags = {}) => {
|
|
31
|
-
metrics.emitCounter(name, counter,
|
|
13
|
+
metrics.emitCounter(name, counter, {
|
|
14
|
+
...tags,
|
|
32
15
|
pathname,
|
|
33
16
|
entry
|
|
34
|
-
})
|
|
17
|
+
});
|
|
35
18
|
};
|
|
36
19
|
return { emitTimer, emitCounter };
|
|
37
20
|
};
|