@modern-js/server 1.4.3 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/js/modern/dev-tools/mock/index.js +1 -1
- package/dist/js/modern/dev-tools/socket-server.js +2 -2
- package/dist/js/modern/index.js +1 -1
- package/dist/js/modern/server/{dev-server/dev-server-split.js → dev-server-split.js} +0 -0
- package/dist/js/modern/server/{dev-server/dev-server.js → dev-server.js} +15 -14
- package/dist/js/modern/server/index.js +15 -138
- package/dist/js/modern/{libs/render/cache/type.js → types.js} +0 -0
- package/dist/js/node/dev-tools/mock/index.js +2 -2
- package/dist/js/node/dev-tools/socket-server.js +2 -3
- package/dist/js/node/index.js +2 -2
- package/dist/js/node/server/{dev-server/dev-server-split.js → dev-server-split.js} +0 -0
- package/dist/js/node/server/{dev-server/dev-server.js → dev-server.js} +18 -24
- package/dist/js/node/server/index.js +17 -152
- package/dist/js/node/{libs/render/cache/type.js → types.js} +0 -0
- package/dist/types/dev-tools/babel/register.d.ts +1 -2
- package/dist/types/dev-tools/dev-server-plugin.d.ts +1 -1
- package/dist/types/dev-tools/launch-editor/index.d.ts +1 -2
- package/dist/types/dev-tools/mock/getMockData.d.ts +1 -2
- package/dist/types/dev-tools/mock/index.d.ts +1 -2
- package/dist/types/dev-tools/socket-server.d.ts +1 -1
- package/dist/types/index.d.ts +4 -5
- package/dist/types/server/{dev-server/dev-server-split.d.ts → dev-server-split.d.ts} +6 -5
- package/dist/types/server/{dev-server/dev-server.d.ts → dev-server.d.ts} +4 -3
- package/dist/types/server/index.d.ts +4 -19
- package/dist/types/types.d.ts +28 -0
- package/modern.config.js +5 -1
- package/package.json +11 -41
- package/tests/server.test.ts +10 -3
- package/dist/js/modern/constants.js +0 -26
- package/dist/js/modern/libs/context/context.js +0 -180
- package/dist/js/modern/libs/context/index.js +0 -3
- package/dist/js/modern/libs/hook-api/route.js +0 -39
- package/dist/js/modern/libs/hook-api/template.js +0 -61
- package/dist/js/modern/libs/metrics.js +0 -12
- package/dist/js/modern/libs/proxy.js +0 -33
- package/dist/js/modern/libs/render/cache/__tests__/cache.fun.test.js +0 -70
- package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +0 -233
- package/dist/js/modern/libs/render/cache/__tests__/cacheable.js +0 -53
- package/dist/js/modern/libs/render/cache/__tests__/error-configuration.js +0 -35
- package/dist/js/modern/libs/render/cache/__tests__/matched-cache.js +0 -121
- package/dist/js/modern/libs/render/cache/index.js +0 -74
- package/dist/js/modern/libs/render/cache/page-caches/index.js +0 -9
- package/dist/js/modern/libs/render/cache/page-caches/lru.js +0 -35
- package/dist/js/modern/libs/render/cache/spr.js +0 -280
- package/dist/js/modern/libs/render/cache/util.js +0 -79
- package/dist/js/modern/libs/render/index.js +0 -65
- package/dist/js/modern/libs/render/modern/browser-list.js +0 -7
- package/dist/js/modern/libs/render/modern/index.js +0 -42
- package/dist/js/modern/libs/render/reader.js +0 -112
- package/dist/js/modern/libs/render/ssr.js +0 -58
- package/dist/js/modern/libs/render/static.js +0 -46
- package/dist/js/modern/libs/render/type.js +0 -7
- package/dist/js/modern/libs/route/index.js +0 -68
- package/dist/js/modern/libs/route/matcher.js +0 -94
- package/dist/js/modern/libs/route/route.js +0 -24
- package/dist/js/modern/libs/serve-file.js +0 -28
- package/dist/js/modern/server/dev-server/index.js +0 -2
- package/dist/js/modern/server/modern-server-split.js +0 -81
- package/dist/js/modern/server/modern-server.js +0 -584
- package/dist/js/modern/type.js +0 -1
- package/dist/js/modern/utils.js +0 -112
- package/dist/js/node/constants.js +0 -36
- package/dist/js/node/libs/context/context.js +0 -194
- package/dist/js/node/libs/context/index.js +0 -18
- package/dist/js/node/libs/hook-api/route.js +0 -48
- package/dist/js/node/libs/hook-api/template.js +0 -69
- package/dist/js/node/libs/metrics.js +0 -18
- package/dist/js/node/libs/proxy.js +0 -44
- package/dist/js/node/libs/render/cache/__tests__/cache.fun.test.js +0 -77
- package/dist/js/node/libs/render/cache/__tests__/cache.test.js +0 -238
- package/dist/js/node/libs/render/cache/__tests__/cacheable.js +0 -60
- package/dist/js/node/libs/render/cache/__tests__/error-configuration.js +0 -42
- package/dist/js/node/libs/render/cache/__tests__/matched-cache.js +0 -128
- package/dist/js/node/libs/render/cache/index.js +0 -86
- package/dist/js/node/libs/render/cache/page-caches/index.js +0 -17
- package/dist/js/node/libs/render/cache/page-caches/lru.js +0 -47
- package/dist/js/node/libs/render/cache/spr.js +0 -298
- package/dist/js/node/libs/render/cache/util.js +0 -105
- package/dist/js/node/libs/render/index.js +0 -91
- package/dist/js/node/libs/render/modern/browser-list.js +0 -14
- package/dist/js/node/libs/render/modern/index.js +0 -58
- package/dist/js/node/libs/render/reader.js +0 -139
- package/dist/js/node/libs/render/ssr.js +0 -76
- package/dist/js/node/libs/render/static.js +0 -62
- package/dist/js/node/libs/render/type.js +0 -14
- package/dist/js/node/libs/route/index.js +0 -83
- package/dist/js/node/libs/route/matcher.js +0 -108
- package/dist/js/node/libs/route/route.js +0 -33
- package/dist/js/node/libs/serve-file.js +0 -41
- package/dist/js/node/server/dev-server/index.js +0 -27
- package/dist/js/node/server/modern-server-split.js +0 -97
- package/dist/js/node/server/modern-server.js +0 -622
- package/dist/js/node/type.js +0 -5
- package/dist/js/node/utils.js +0 -143
- package/dist/types/constants.d.ts +0 -20
- package/dist/types/libs/context/context.d.ts +0 -61
- package/dist/types/libs/context/index.d.ts +0 -4
- package/dist/types/libs/hook-api/route.d.ts +0 -14
- package/dist/types/libs/hook-api/template.d.ts +0 -14
- package/dist/types/libs/metrics.d.ts +0 -3
- package/dist/types/libs/proxy.d.ts +0 -4
- package/dist/types/libs/render/cache/__tests__/cache.fun.test.d.ts +0 -1
- package/dist/types/libs/render/cache/__tests__/cache.test.d.ts +0 -1
- package/dist/types/libs/render/cache/__tests__/cacheable.d.ts +0 -62
- package/dist/types/libs/render/cache/__tests__/error-configuration.d.ts +0 -28
- package/dist/types/libs/render/cache/__tests__/matched-cache.d.ts +0 -124
- package/dist/types/libs/render/cache/index.d.ts +0 -6
- package/dist/types/libs/render/cache/page-caches/index.d.ts +0 -2
- package/dist/types/libs/render/cache/page-caches/lru.d.ts +0 -15
- package/dist/types/libs/render/cache/spr.d.ts +0 -24
- package/dist/types/libs/render/cache/type.d.ts +0 -48
- package/dist/types/libs/render/cache/util.d.ts +0 -17
- package/dist/types/libs/render/index.d.ts +0 -18
- package/dist/types/libs/render/modern/browser-list.d.ts +0 -1
- package/dist/types/libs/render/modern/index.d.ts +0 -3
- package/dist/types/libs/render/reader.d.ts +0 -18
- package/dist/types/libs/render/ssr.d.ts +0 -10
- package/dist/types/libs/render/static.d.ts +0 -3
- package/dist/types/libs/render/type.d.ts +0 -34
- package/dist/types/libs/route/index.d.ts +0 -15
- package/dist/types/libs/route/matcher.d.ts +0 -15
- package/dist/types/libs/route/route.d.ts +0 -14
- package/dist/types/libs/serve-file.d.ts +0 -8
- package/dist/types/server/dev-server/index.d.ts +0 -2
- package/dist/types/server/modern-server-split.d.ts +0 -26
- package/dist/types/server/modern-server.d.ts +0 -72
- package/dist/types/type.d.ts +0 -80
- package/dist/types/utils.d.ts +0 -19
- package/tests/context.test.ts +0 -52
- package/tests/fixtures/hosting-files/static/index.js +0 -1
- package/tests/fixtures/reader/index.ts +0 -3
- package/tests/fixtures/route-spec/dynamic.json +0 -13
- package/tests/fixtures/route-spec/index.json +0 -29
- package/tests/fixtures/ssr/bundle.js +0 -5
- package/tests/fixtures/static-dir/bar.html +0 -11
- package/tests/fixtures/static-dir/baz/index.html +0 -11
- package/tests/fixtures/static-dir/foo/index.html +0 -11
- package/tests/helper.ts +0 -8
- package/tests/hook.test.ts +0 -44
- package/tests/middleware.test.ts +0 -179
- package/tests/render.test.ts +0 -102
- package/tests/route.test.ts +0 -77
- package/tests/utils.test.ts +0 -106
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/member-ordering */
|
|
2
|
-
|
|
3
|
-
/* eslint-disable no-lone-blocks */
|
|
4
|
-
import crypto from 'crypto';
|
|
5
|
-
import LRUCache from 'lru-cache';
|
|
6
|
-
import mime from 'mime-types';
|
|
7
|
-
import { cacheAddition, connectFactor, fname, maybeSync, namespaceHash, valueFactory, withCoalescedInvoke } from "./util";
|
|
8
|
-
import { createPageCaches } from "./page-caches";
|
|
9
|
-
const MAX_CACHE_EACH_REQ = Number(process.env.ROUTE_CACHE_LIMIT) || 10;
|
|
10
|
-
const MAX_SIZE_EACH_CLUSTER = Number(process.env.CLUSTER_CACHE_LIMIT) || 100;
|
|
11
|
-
const BASE_LEVEL = 0;
|
|
12
|
-
const QUERY_LEVEL = 1;
|
|
13
|
-
const HEADER_LEVEL = 2;
|
|
14
|
-
const QUERY_HEADER_LEVEL = 3;
|
|
15
|
-
|
|
16
|
-
class CacheManager {
|
|
17
|
-
constructor(cacheOptions) {
|
|
18
|
-
this.cache = void 0;
|
|
19
|
-
this.cacheOptions = void 0;
|
|
20
|
-
|
|
21
|
-
this.find = (() => {
|
|
22
|
-
{
|
|
23
|
-
// eslint-disable-next-line consistent-this,@typescript-eslint/no-this-alias
|
|
24
|
-
const _this = this;
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
[fname(BASE_LEVEL)](context, cacheKey // data: CacheContent,
|
|
28
|
-
) {
|
|
29
|
-
return _this.md5(cacheKey);
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
[fname(QUERY_LEVEL)](context, cacheKey, data) {
|
|
33
|
-
const queryFactor = _this.queryFactor(context, data);
|
|
34
|
-
|
|
35
|
-
if (!queryFactor) {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return _this.md5(connectFactor(cacheKey, queryFactor));
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
[fname(HEADER_LEVEL)](context, cacheKey, data) {
|
|
43
|
-
const headerFactor = _this.headerFactor(context, data);
|
|
44
|
-
|
|
45
|
-
if (!headerFactor) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return _this.md5(connectFactor(cacheKey, headerFactor));
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
[fname(QUERY_HEADER_LEVEL)](context, cacheKey, data) {
|
|
53
|
-
const queryFactor = _this.queryFactor(context, data);
|
|
54
|
-
|
|
55
|
-
const headerFactor = _this.headerFactor(context, data);
|
|
56
|
-
|
|
57
|
-
if (!queryFactor || !headerFactor) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return _this.md5(connectFactor(cacheKey, headerFactor, queryFactor));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
})();
|
|
67
|
-
|
|
68
|
-
this.cacheOptions = cacheOptions;
|
|
69
|
-
this.cache = new LRUCache({
|
|
70
|
-
max: Math.min(MAX_SIZE_EACH_CLUSTER, 600) * 1024 * 1024,
|
|
71
|
-
|
|
72
|
-
// 默认存 100M,最大 600M
|
|
73
|
-
length(n) {
|
|
74
|
-
const len = n.caches.keys().reduce((total, cur) => {
|
|
75
|
-
var _n$caches$peek;
|
|
76
|
-
|
|
77
|
-
return total + (((_n$caches$peek = n.caches.peek(cur)) === null || _n$caches$peek === void 0 ? void 0 : _n$caches$peek.size) || 0);
|
|
78
|
-
}, 1);
|
|
79
|
-
return len;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
md5(content) {
|
|
86
|
-
const md5 = crypto.createHash('md5');
|
|
87
|
-
return md5.update(content).digest('hex');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
generateRequestKey(context) {
|
|
91
|
-
const {
|
|
92
|
-
pathname,
|
|
93
|
-
entry
|
|
94
|
-
} = context;
|
|
95
|
-
return this.md5(`${pathname}_${entry}`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
replaceValue(value, matcher) {
|
|
99
|
-
let final = value;
|
|
100
|
-
Object.keys(matcher).some(replacer => {
|
|
101
|
-
const reg = new RegExp(matcher[replacer]);
|
|
102
|
-
|
|
103
|
-
if (reg.test(value)) {
|
|
104
|
-
final = replacer;
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return false;
|
|
109
|
-
});
|
|
110
|
-
return final;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
factor(keys, obj, matches = {}) {
|
|
114
|
-
keys.sort();
|
|
115
|
-
const getValue = valueFactory(obj);
|
|
116
|
-
const factorAry = keys.reduce((ary, key) => {
|
|
117
|
-
let value = getValue(key) || '';
|
|
118
|
-
const matcher = matches[key];
|
|
119
|
-
|
|
120
|
-
if (matcher) {
|
|
121
|
-
value = this.replaceValue(value, matcher);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return ary.concat([key, value]);
|
|
125
|
-
}, []);
|
|
126
|
-
return factorAry.join(',');
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
queryFactor(context, data) {
|
|
130
|
-
var _data$includes, _data$matches;
|
|
131
|
-
|
|
132
|
-
const queryKeys = (_data$includes = data.includes) === null || _data$includes === void 0 ? void 0 : _data$includes.query;
|
|
133
|
-
const queryMatches = (_data$matches = data.matches) === null || _data$matches === void 0 ? void 0 : _data$matches.query;
|
|
134
|
-
|
|
135
|
-
if (!queryKeys || queryKeys.length === 0) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const requestQuery = context.query;
|
|
140
|
-
const queryFactor = this.factor(queryKeys, requestQuery, queryMatches);
|
|
141
|
-
return queryFactor;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
headerFactor(context, data) {
|
|
145
|
-
var _data$includes2, _data$matches2;
|
|
146
|
-
|
|
147
|
-
const headerKeys = (_data$includes2 = data.includes) === null || _data$includes2 === void 0 ? void 0 : _data$includes2.header;
|
|
148
|
-
const headerMatches = (_data$matches2 = data.matches) === null || _data$matches2 === void 0 ? void 0 : _data$matches2.header;
|
|
149
|
-
|
|
150
|
-
if (!headerKeys || headerKeys.length === 0) {
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const requestHeader = context.headers;
|
|
155
|
-
const headerFactor = this.factor(headerKeys, requestHeader, headerMatches);
|
|
156
|
-
return headerFactor;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async best(context, cacheKey, data) {
|
|
160
|
-
const {
|
|
161
|
-
level
|
|
162
|
-
} = data;
|
|
163
|
-
const cacheHash = this.find[fname(level)](context, cacheKey, data);
|
|
164
|
-
|
|
165
|
-
if (!cacheHash) {
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return data.caches.get(cacheHash);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
createCacheContent(config, caches) {
|
|
173
|
-
return {
|
|
174
|
-
level: config.level,
|
|
175
|
-
interval: config.interval,
|
|
176
|
-
includes: config.includes || null,
|
|
177
|
-
limit: config.staleLimit,
|
|
178
|
-
matches: config.matches || null,
|
|
179
|
-
caches
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async get(context) {
|
|
184
|
-
const cacheKey = this.generateRequestKey(context);
|
|
185
|
-
const data = this.cache.get(cacheKey); // no cache key matched
|
|
186
|
-
|
|
187
|
-
if (!data) {
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const dest = await this.best(context, cacheKey, data); // no cache for current page with current config
|
|
192
|
-
|
|
193
|
-
if (!dest) {
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const {
|
|
198
|
-
expireTime,
|
|
199
|
-
limitTime,
|
|
200
|
-
html,
|
|
201
|
-
cacheHash
|
|
202
|
-
} = dest;
|
|
203
|
-
const isStale = Date.now() - expireTime > 0;
|
|
204
|
-
const isGarbage = limitTime ? Date.now() - limitTime > 0 : false;
|
|
205
|
-
return {
|
|
206
|
-
content: html || '',
|
|
207
|
-
contentType: mime.contentType('html'),
|
|
208
|
-
isStale,
|
|
209
|
-
isGarbage,
|
|
210
|
-
hash: cacheHash
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
async set(context, html, cacheConfig, sync = false) {
|
|
215
|
-
if (!cacheConfig) {
|
|
216
|
-
return false;
|
|
217
|
-
} // each version with route is a separate cache
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const cacheKey = this.generateRequestKey(context);
|
|
221
|
-
let data = this.cache.get(cacheKey);
|
|
222
|
-
|
|
223
|
-
if (!data) {
|
|
224
|
-
const caches = await createPageCaches(MAX_CACHE_EACH_REQ); // eslint-disable-next-line require-atomic-updates
|
|
225
|
-
|
|
226
|
-
data = this.createCacheContent(cacheConfig, caches);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const cacheHash = this.find[fname(cacheConfig.level)](context, cacheKey, data); // if cacheHash is null, maybe level not match meta key, do not cache
|
|
230
|
-
|
|
231
|
-
if (!cacheHash) {
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const cacheSyncOrAsync = async () => {
|
|
236
|
-
const next = data;
|
|
237
|
-
const limit = cacheConfig.staleLimit;
|
|
238
|
-
const storeHTML = cacheAddition(html, cacheHash);
|
|
239
|
-
const size = storeHTML.length;
|
|
240
|
-
await next.caches.set(cacheHash, {
|
|
241
|
-
expireTime: Date.now() + cacheConfig.interval * 1000,
|
|
242
|
-
limitTime: typeof limit === 'number' ? Date.now() + limit * 1000 : null,
|
|
243
|
-
cacheHash,
|
|
244
|
-
html: storeHTML,
|
|
245
|
-
size
|
|
246
|
-
});
|
|
247
|
-
this.cache.set(cacheKey, next);
|
|
248
|
-
return true;
|
|
249
|
-
}; // cache set is async, each hash is cached only once at the same time
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const doCache = withCoalescedInvoke(cacheSyncOrAsync).bind(null, namespaceHash('stream', cacheHash), []);
|
|
253
|
-
return maybeSync(doCache)(sync);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
async del(context, cacheHash) {
|
|
257
|
-
const cacheKey = this.generateRequestKey(context);
|
|
258
|
-
const data = this.cache.get(cacheKey);
|
|
259
|
-
data === null || data === void 0 ? void 0 : data.caches.del(cacheHash);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
let manager;
|
|
265
|
-
export function createCache() {
|
|
266
|
-
if (manager) {
|
|
267
|
-
return manager;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
manager = new CacheManager({
|
|
271
|
-
max: 0
|
|
272
|
-
});
|
|
273
|
-
return manager;
|
|
274
|
-
}
|
|
275
|
-
export function destroyCache() {
|
|
276
|
-
manager = null;
|
|
277
|
-
}
|
|
278
|
-
/* eslint-enable no-lone-blocks */
|
|
279
|
-
|
|
280
|
-
/* eslint-enable @typescript-eslint/member-ordering */
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import url from 'url';
|
|
2
|
-
export function namespaceHash(namespace, hash) {
|
|
3
|
-
return `${namespace}/${hash}`;
|
|
4
|
-
}
|
|
5
|
-
export function fname(lv) {
|
|
6
|
-
return `f${lv}`;
|
|
7
|
-
}
|
|
8
|
-
export function connectFactor(...args) {
|
|
9
|
-
return args.join('-');
|
|
10
|
-
}
|
|
11
|
-
export function valueFactory(obj) {
|
|
12
|
-
if (obj instanceof url.URLSearchParams) {
|
|
13
|
-
return function (key) {
|
|
14
|
-
return obj.get(key);
|
|
15
|
-
};
|
|
16
|
-
} else {
|
|
17
|
-
return function (key) {
|
|
18
|
-
const value = obj[key];
|
|
19
|
-
|
|
20
|
-
if (Array.isArray(value)) {
|
|
21
|
-
return value.join(',');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return value;
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
export function getTime([s, ns]) {
|
|
29
|
-
return Math.floor(s * 1e3 + ns / 1e6);
|
|
30
|
-
}
|
|
31
|
-
const RE_START_IN_HEAD = /<head>/;
|
|
32
|
-
export function cacheAddition(html, hash) {
|
|
33
|
-
const additionHtml = html.replace(RE_START_IN_HEAD, `<head><meta name="x-moden-spr" content="${hash}">`);
|
|
34
|
-
return additionHtml;
|
|
35
|
-
}
|
|
36
|
-
const globalInvokeCache = new Map();
|
|
37
|
-
export function withCoalescedInvoke(func) {
|
|
38
|
-
return async function (key, args) {
|
|
39
|
-
const entry = globalInvokeCache.get(key);
|
|
40
|
-
|
|
41
|
-
if (entry) {
|
|
42
|
-
// eslint-disable-next-line promise/prefer-await-to-then
|
|
43
|
-
return entry.then(res => ({
|
|
44
|
-
isOrigin: false,
|
|
45
|
-
value: res.value
|
|
46
|
-
}));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function __wrapper() {
|
|
50
|
-
return func(...args);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const future = __wrapper() // eslint-disable-next-line promise/prefer-await-to-then
|
|
54
|
-
.then(res => {
|
|
55
|
-
globalInvokeCache.delete(key);
|
|
56
|
-
return {
|
|
57
|
-
isOrigin: true,
|
|
58
|
-
value: res
|
|
59
|
-
};
|
|
60
|
-
}) // eslint-disable-next-line promise/prefer-await-to-then
|
|
61
|
-
.catch(err => {
|
|
62
|
-
globalInvokeCache.delete(key);
|
|
63
|
-
throw err;
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
globalInvokeCache.set(key, future);
|
|
67
|
-
return future;
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
export function maybeSync(fn) {
|
|
71
|
-
return sync => {
|
|
72
|
-
if (sync) {
|
|
73
|
-
return fn();
|
|
74
|
-
} else {
|
|
75
|
-
fn();
|
|
76
|
-
return Promise.resolve();
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { fs } from '@modern-js/utils';
|
|
3
|
-
import mime from 'mime-types';
|
|
4
|
-
import { ERROR_DIGEST } from "../../constants";
|
|
5
|
-
import { handleDirectory } from "./static";
|
|
6
|
-
import { readFile } from "./reader";
|
|
7
|
-
import * as ssr from "./ssr";
|
|
8
|
-
import { supportModern, getModernEntry } from "./modern";
|
|
9
|
-
export const createRenderHandler = ({
|
|
10
|
-
distDir,
|
|
11
|
-
staticGenerate
|
|
12
|
-
}) => async function render({
|
|
13
|
-
ctx,
|
|
14
|
-
route,
|
|
15
|
-
runner
|
|
16
|
-
}) {
|
|
17
|
-
if (ctx.resHasHandled()) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const {
|
|
22
|
-
entryPath,
|
|
23
|
-
urlPath
|
|
24
|
-
} = route;
|
|
25
|
-
const entry = path.join(distDir, entryPath);
|
|
26
|
-
|
|
27
|
-
if (!route.isSPA) {
|
|
28
|
-
const result = await handleDirectory(ctx, entry, urlPath);
|
|
29
|
-
return result;
|
|
30
|
-
} // only spa can use es6-html
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const modernEntry = getModernEntry(entry);
|
|
34
|
-
const useModern = // route.enableModernMode &&
|
|
35
|
-
supportModern(ctx) && fs.existsSync(modernEntry);
|
|
36
|
-
const templateHTML = useModern ? modernEntry : entry; // handles ssr first
|
|
37
|
-
|
|
38
|
-
if (route.isSSR) {
|
|
39
|
-
try {
|
|
40
|
-
const result = await ssr.render(ctx, {
|
|
41
|
-
distDir,
|
|
42
|
-
entryName: route.entryName,
|
|
43
|
-
urlPath: route.urlPath,
|
|
44
|
-
bundle: route.bundle,
|
|
45
|
-
template: templateHTML,
|
|
46
|
-
staticGenerate
|
|
47
|
-
}, runner);
|
|
48
|
-
return result;
|
|
49
|
-
} catch (err) {
|
|
50
|
-
ctx.error(ERROR_DIGEST.ERENDER, err.stack);
|
|
51
|
-
ctx.res.setHeader('x-modern-ssr-fallback', '1');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const content = await readFile(templateHTML);
|
|
56
|
-
|
|
57
|
-
if (!content) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
content,
|
|
63
|
-
contentType: mime.contentType(path.extname(templateHTML))
|
|
64
|
-
};
|
|
65
|
-
};
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import Parser from 'ua-parser-js';
|
|
2
|
-
import compareVersions from 'compare-versions';
|
|
3
|
-
import { NativeModuleNameMap } from "./browser-list";
|
|
4
|
-
|
|
5
|
-
const nativeModules = require('@babel/compat-data/native-modules');
|
|
6
|
-
|
|
7
|
-
export const supportModern = context => {
|
|
8
|
-
if (context.query.modern_es6) {
|
|
9
|
-
return true;
|
|
10
|
-
} // no ua in request headers
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const userAgent = context.headers['user-agent'];
|
|
14
|
-
|
|
15
|
-
if (!userAgent || typeof userAgent !== 'string') {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const parsedUA = Parser(userAgent);
|
|
20
|
-
const browserName = parsedUA.browser.name;
|
|
21
|
-
const browserVersion = parsedUA.browser.version;
|
|
22
|
-
|
|
23
|
-
if (!browserName || !browserVersion) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const nativeUAName = NativeModuleNameMap[browserName];
|
|
28
|
-
|
|
29
|
-
if (!nativeUAName) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const version = nativeModules['es6.module'][nativeUAName];
|
|
34
|
-
|
|
35
|
-
if (!version) {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const result = compareVersions(browserVersion, version);
|
|
40
|
-
return result >= 0;
|
|
41
|
-
};
|
|
42
|
-
export const getModernEntry = filepath => filepath.replace(/\.html$/, '-es6.html');
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { fs } from '@modern-js/utils';
|
|
2
|
-
import LRU from 'lru-cache';
|
|
3
|
-
const Byte = 1;
|
|
4
|
-
const KB = 1024 * Byte;
|
|
5
|
-
const MB = 1024 * KB;
|
|
6
|
-
|
|
7
|
-
const getContentLength = cache => cache.content.length;
|
|
8
|
-
|
|
9
|
-
const createCacheItem = async (filepath, mtime) => {
|
|
10
|
-
const content = await fs.readFile(filepath);
|
|
11
|
-
return {
|
|
12
|
-
content,
|
|
13
|
-
mtime
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export class LruReader {
|
|
18
|
-
// private timer?: NodeJS.Timeout;
|
|
19
|
-
constructor() {
|
|
20
|
-
this.cache = void 0;
|
|
21
|
-
this.cache = new LRU({
|
|
22
|
-
max: 256 * MB,
|
|
23
|
-
length: getContentLength,
|
|
24
|
-
maxAge: 5 * 60 * 5000 // 60s
|
|
25
|
-
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
init() {// this.timeTask();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
close() {// if (this.timer) {
|
|
33
|
-
// clearInterval(this.timer);
|
|
34
|
-
// }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async read(filepath) {
|
|
38
|
-
if (this.cache.has(filepath)) {
|
|
39
|
-
const {
|
|
40
|
-
content
|
|
41
|
-
} = this.cache.get(filepath);
|
|
42
|
-
return {
|
|
43
|
-
content
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!fs.existsSync(filepath)) {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const stat = fs.statSync(filepath);
|
|
52
|
-
|
|
53
|
-
if (stat.isDirectory()) {
|
|
54
|
-
return null;
|
|
55
|
-
} // if file more than 20 MB
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (stat.size > 20 * MB) {
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const item = await createCacheItem(filepath, stat.mtime);
|
|
63
|
-
this.cache.set(filepath, item);
|
|
64
|
-
return item;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
update() {
|
|
68
|
-
const {
|
|
69
|
-
cache
|
|
70
|
-
} = this;
|
|
71
|
-
const files = cache.keys();
|
|
72
|
-
|
|
73
|
-
for (const filepath of files) {
|
|
74
|
-
if (!fs.existsSync(filepath)) {
|
|
75
|
-
cache.del(filepath);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
const item = cache.get(filepath);
|
|
80
|
-
const stat = fs.statSync(filepath);
|
|
81
|
-
const {
|
|
82
|
-
mtime
|
|
83
|
-
} = stat; // file is modify
|
|
84
|
-
|
|
85
|
-
if (item.mtime < mtime) {
|
|
86
|
-
cache.del(filepath);
|
|
87
|
-
}
|
|
88
|
-
} catch (e) {
|
|
89
|
-
// for safe
|
|
90
|
-
cache.del(filepath);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
} // private timeTask() {
|
|
94
|
-
// this.timer = setInterval(() => this.update, 5 * 60 * 1000).unref();
|
|
95
|
-
// }
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
const reader = new LruReader();
|
|
100
|
-
export const readFile = async filepath => {
|
|
101
|
-
const file = await reader.read(filepath);
|
|
102
|
-
return file === null || file === void 0 ? void 0 : file.content;
|
|
103
|
-
};
|
|
104
|
-
export const updateFile = () => {
|
|
105
|
-
reader.update();
|
|
106
|
-
};
|
|
107
|
-
export const init = () => {
|
|
108
|
-
reader.init();
|
|
109
|
-
};
|
|
110
|
-
export const close = () => {
|
|
111
|
-
reader.close();
|
|
112
|
-
};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { SERVER_RENDER_FUNCTION_NAME } from '@modern-js/utils';
|
|
3
|
-
import mime from 'mime-types';
|
|
4
|
-
import cookie from 'cookie';
|
|
5
|
-
import cache from "./cache";
|
|
6
|
-
export const render = async (ctx, renderOptions, runner) => {
|
|
7
|
-
const {
|
|
8
|
-
urlPath,
|
|
9
|
-
bundle,
|
|
10
|
-
distDir,
|
|
11
|
-
template,
|
|
12
|
-
entryName,
|
|
13
|
-
staticGenerate
|
|
14
|
-
} = renderOptions;
|
|
15
|
-
const bundleJS = path.join(distDir, bundle);
|
|
16
|
-
const context = {
|
|
17
|
-
request: {
|
|
18
|
-
baseUrl: urlPath,
|
|
19
|
-
params: ctx.params,
|
|
20
|
-
pathname: ctx.path,
|
|
21
|
-
host: ctx.host,
|
|
22
|
-
query: ctx.query,
|
|
23
|
-
url: ctx.href,
|
|
24
|
-
cookieMap: cookie.parse(ctx.headers.cookie || ''),
|
|
25
|
-
headers: ctx.headers
|
|
26
|
-
},
|
|
27
|
-
redirection: {},
|
|
28
|
-
template,
|
|
29
|
-
entryName,
|
|
30
|
-
distDir,
|
|
31
|
-
staticGenerate,
|
|
32
|
-
logger: ctx.logger,
|
|
33
|
-
metrics: ctx.metrics
|
|
34
|
-
};
|
|
35
|
-
runner.extendSSRContext(context);
|
|
36
|
-
|
|
37
|
-
const serverRender = require(bundleJS)[SERVER_RENDER_FUNCTION_NAME];
|
|
38
|
-
|
|
39
|
-
const html = await cache(serverRender, ctx)(context);
|
|
40
|
-
const {
|
|
41
|
-
url,
|
|
42
|
-
status = 302
|
|
43
|
-
} = context.redirection;
|
|
44
|
-
|
|
45
|
-
if (url) {
|
|
46
|
-
return {
|
|
47
|
-
content: url,
|
|
48
|
-
contentType: '',
|
|
49
|
-
statusCode: status,
|
|
50
|
-
redirect: true
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
content: html,
|
|
56
|
-
contentType: mime.contentType('html')
|
|
57
|
-
};
|
|
58
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import mime from 'mime-types';
|
|
3
|
-
import { readFile } from "./reader";
|
|
4
|
-
export async function handleDirectory(ctx, entryPath, urlPath) {
|
|
5
|
-
const {
|
|
6
|
-
path: pathname
|
|
7
|
-
} = ctx;
|
|
8
|
-
const filepath = path.join(entryPath, trimLeft(pathname, urlPath)); // If can match accurately, always return the one that matches accurately
|
|
9
|
-
|
|
10
|
-
let content = await readFile(filepath);
|
|
11
|
-
let contentType = mime.contentType(path.extname(filepath) || ''); // automatic addressing
|
|
12
|
-
|
|
13
|
-
if (!content) {
|
|
14
|
-
if (pathname.endsWith('/')) {
|
|
15
|
-
content = await readFile(`${filepath}index.html`);
|
|
16
|
-
} else if (!pathname.includes('.')) {
|
|
17
|
-
content = await readFile(`${filepath}.html`);
|
|
18
|
-
|
|
19
|
-
if (!content) {
|
|
20
|
-
content = await readFile(`${filepath}/index.html`);
|
|
21
|
-
}
|
|
22
|
-
} // set content-type as html
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (content) {
|
|
26
|
-
contentType = mime.contentType('html');
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (!content) {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
content,
|
|
36
|
-
contentType: contentType || ''
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const trimLeft = (str, prefix) => {
|
|
41
|
-
if (str.startsWith(prefix)) {
|
|
42
|
-
return str.substring(prefix.length);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return str;
|
|
46
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export let RenderLevel;
|
|
2
|
-
|
|
3
|
-
(function (RenderLevel) {
|
|
4
|
-
RenderLevel[RenderLevel["CLIENT_RENDER"] = 0] = "CLIENT_RENDER";
|
|
5
|
-
RenderLevel[RenderLevel["SERVER_PREFETCH"] = 1] = "SERVER_PREFETCH";
|
|
6
|
-
RenderLevel[RenderLevel["SERVER_RENDER"] = 2] = "SERVER_RENDER";
|
|
7
|
-
})(RenderLevel || (RenderLevel = {}));
|