forked from web-infra-dev/modern.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
89 lines (81 loc) · 2.32 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { IncomingMessage } from 'http';
import { Transform } from 'stream';
import {
CacheControl,
CacheOption,
CacheOptionProvider,
} from '@modern-js/types';
import { createMemoryStorage } from '@modern-js/runtime-utils/storer';
import { RenderFunction, SSRServerContext } from '../type';
import { cacheMod } from './cacheMod';
import { CacheManager, CacheResult } from './manager';
const cacheStorage = createMemoryStorage<string>('__ssr__cache');
export async function ssrCache(
req: IncomingMessage,
render: RenderFunction,
ssrContext: SSRServerContext,
): Promise<CacheResult> {
const { customContainer, cacheOption } = cacheMod;
const cacheControl = await matchCacheControl(req, cacheOption);
const cacheManager = new CacheManager(
customContainer ? customContainer : cacheStorage,
);
if (cacheControl) {
return cacheManager.getCacheResult(req, cacheControl, render, ssrContext);
} else {
const renderResult = await render(ssrContext);
if (!renderResult) {
return {
data: '',
};
} else if (typeof renderResult === 'string') {
return {
data: renderResult,
};
} else {
const stream = new Transform({
write(chunk, _, callback) {
this.push(chunk);
callback();
},
});
const data = await renderResult(stream);
return {
data,
};
}
}
}
async function matchCacheControl(
req: IncomingMessage,
cacheOption?: CacheOption,
): Promise<CacheControl | undefined> {
if (!cacheOption) {
return undefined;
} else if (isCacheControl(cacheOption)) {
return cacheOption;
} else if (isCacheOptionProvider(cacheOption)) {
return cacheOption(req);
} else {
const url = req.url!;
const options = Object.entries(cacheOption);
for (const [key, option] of options) {
if (key === '*' || new RegExp(key).test(url)) {
if (typeof option === 'function') {
return option(req);
} else {
return option;
}
}
}
return undefined;
}
function isCacheOptionProvider(
option: CacheOption,
): option is CacheOptionProvider {
return typeof option === 'function';
}
function isCacheControl(option: CacheOption): option is CacheControl {
return typeof option === 'object' && option !== null && 'maxAge' in option;
}
}