server.tpl
3.62 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// umi.server.js
import '{{{ RuntimePolyfill }}}';
import { format } from 'url';
import renderServer from '{{{ Renderer }}}';
import { stripBasename, cheerio, handleHTML } from '{{{ Utils }}}';
import { IServerRender } from '@umijs/types';
import { ApplyPluginsType, createMemoryHistory{{ #DynamicImport }}, dynamic{{ /DynamicImport }} } from '{{{ RuntimePath }}}';
{{ #loadingComponent }}
import LoadingComponent from '{{{ loadingComponent }}}';
{{ /loadingComponent }}
import { plugin } from './plugin';
import './pluginRegister';
// origin require module
// https://github.com/webpack/webpack/issues/4175#issuecomment-342931035
const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
/**
* server render function
* @param params
*/
const render: IServerRender = async (params) => {
let error;
const {
origin = '',
path,
htmlTemplate = '',
mountElementId = '{{{ MountElementId }}}',
context = {},
mode = '{{{ Mode }}}',
basename = '{{{ Basename }}}',
staticMarkup = {{{ StaticMarkup }}},
forceInitial = {{{ ForceInitial }}},
removeWindowInitialProps = {{{ RemoveWindowInitialProps }}},
getInitialPropsCtx,
} = params;
let manifest = params.manifest;
const env = '{{{ Env }}}';
let html = htmlTemplate || {{{ DEFAULT_HTML_PLACEHOLDER }}};
let rootContainer = '';
try {
// handle basename
const location = stripBasename(basename, `${origin}${path}`);
const { pathname } = location;
// server history
const history = createMemoryHistory({
initialEntries: [format(location)],
});
/**
* beforeRenderServer hook, for polyfill global.*
*/
await plugin.applyPlugins({
key: 'ssr.beforeRenderServer',
type: ApplyPluginsType.event,
args: {
env,
path,
context,
history,
mode,
location,
},
async: true,
});
/**
* routes init and patch only once
* beforeRenderServer must before routes init avoding require error
*/
// 主要为后面支持按需服务端渲染,单独用 routes 会全编译
const routes = {{{ Routes }}};
// allow user to extend routes
plugin.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: { routes },
});
// for renderServer
const opts = {
path,
history,
pathname,
getInitialPropsCtx,
basename,
context,
mode,
plugin,
staticMarkup,
routes,
isServer: process.env.__IS_SERVER,
}
const dynamicImport = {{{ DynamicImport }}};
if (dynamicImport && !manifest) {
try {
// prerender not work because the manifest generation behind of the prerender
manifest = requireFunc(`./{{{ ManifestFileName }}}`);
} catch (_) {}
}
// renderServer get rootContainer
const { pageHTML, pageInitialProps, routesMatched } = await renderServer(opts);
rootContainer = pageHTML;
if (html) {
// plugin for modify html template
html = await plugin.applyPlugins({
key: 'ssr.modifyServerHTML',
type: ApplyPluginsType.modify,
initialValue: html,
args: {
context,
cheerio,
routesMatched,
dynamicImport,
manifest
},
async: true,
});
html = await handleHTML({ html, rootContainer, pageInitialProps, mountElementId, mode, forceInitial, removeWindowInitialProps, routesMatched, dynamicImport, manifest });
}
} catch (e) {
// downgrade into csr
error = e;
}
return {
rootContainer,
error,
html,
}
}
export default render;