@norejs/ssr-server 0.0.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/README.md +11 -0
- package/index.js +119 -0
- package/package.json +22 -0
package/README.md
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// 导出一个函数,用于启动express 服务器
|
|
2
|
+
// 需要的参数:环境变量,CSR服务器地址,SSR端口号,CSR入口文件地址
|
|
3
|
+
// 启动express 服务器
|
|
4
|
+
const express = require('express');
|
|
5
|
+
const http = require('http');
|
|
6
|
+
const httpProxy = require('http-proxy');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { createProxyMiddleware } = require('http-proxy-middleware');
|
|
9
|
+
const fs = require('fs-extra');
|
|
10
|
+
module.exports = function SSRServer(config, envName, cb) {
|
|
11
|
+
function getPathFromSSRDsit(...args) {
|
|
12
|
+
return path.resolve(process.cwd(), config.ssr.dist, ...args);
|
|
13
|
+
}
|
|
14
|
+
function getPathFromCSRDist(...args) {
|
|
15
|
+
return path.resolve(process.cwd(), config.csr.dist, ...args);
|
|
16
|
+
}
|
|
17
|
+
const ssrEntry = getPathFromSSRDsit('server.js');
|
|
18
|
+
const ssrManifest = getPathFromSSRDsit('asset-manifest.json');
|
|
19
|
+
const ssrPort = config.ssr.port || 8080;
|
|
20
|
+
const renderApp = require(ssrEntry).default;
|
|
21
|
+
const app = express();
|
|
22
|
+
const server = http.createServer(app);
|
|
23
|
+
const csrUrl = config.csrUrl;
|
|
24
|
+
if (csrUrl) {
|
|
25
|
+
const proxy = httpProxy.createProxyServer({ target: csrUrl, ws: true });
|
|
26
|
+
server.on('upgrade', function (req, socket, head) {
|
|
27
|
+
console.log('proxying upgrade request', req.url);
|
|
28
|
+
proxy.ws(req, socket, head);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function getCSRHtml() {
|
|
33
|
+
let html = '';
|
|
34
|
+
if (csrUrl) {
|
|
35
|
+
html = await fetchFile(csrUrl);
|
|
36
|
+
} else {
|
|
37
|
+
html = await fs.readFile(getPathFromCSRDist('index.html'), 'utf-8');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const manifestJson = require(ssrManifest);
|
|
42
|
+
if (manifestJson?.files['main.css']) {
|
|
43
|
+
html = html.replace(
|
|
44
|
+
'</head>',
|
|
45
|
+
`<script>
|
|
46
|
+
window.addEventListener('load', function () {
|
|
47
|
+
var link = document.getElementById('ssr-main');
|
|
48
|
+
link.parentNode.removeChild(link);
|
|
49
|
+
})
|
|
50
|
+
</script><link id="ssr-main" rel="stylesheet" href="${manifestJson?.files['main.css']}"></link></head>`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.log('error', error);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return html;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
app.get('/*', async (req, res, next) => {
|
|
61
|
+
// 有后缀名或者是静态资源不处理
|
|
62
|
+
if (
|
|
63
|
+
req.originalUrl.indexOf('.') > -1 ||
|
|
64
|
+
req.originalUrl.startsWith('/static')
|
|
65
|
+
) {
|
|
66
|
+
return next();
|
|
67
|
+
}
|
|
68
|
+
const { preloadedState, html, css } = await renderApp(req);
|
|
69
|
+
const appString = html;
|
|
70
|
+
if (!appString) {
|
|
71
|
+
return next();
|
|
72
|
+
}
|
|
73
|
+
// 通过csrUrl 获取csr的html
|
|
74
|
+
const csrHtml = await getCSRHtml();
|
|
75
|
+
const initialState = preloadedState;
|
|
76
|
+
const data = csrHtml
|
|
77
|
+
.replace('</head>', `<style>${css}</style></head>`)
|
|
78
|
+
.replace(
|
|
79
|
+
'<div id="root">',
|
|
80
|
+
`<div id="root"><script>window._INIT_STORE_STATE=${JSON.stringify(
|
|
81
|
+
initialState
|
|
82
|
+
)}</script>${appString}`
|
|
83
|
+
);
|
|
84
|
+
return res.send(data);
|
|
85
|
+
});
|
|
86
|
+
app.use(express.static(getPathFromSSRDsit()));
|
|
87
|
+
if (csrUrl) {
|
|
88
|
+
app.use(
|
|
89
|
+
'/*',
|
|
90
|
+
createProxyMiddleware({ target: csrUrl, changeOrigin: true })
|
|
91
|
+
);
|
|
92
|
+
} else if (config.csr.dist) {
|
|
93
|
+
app.use(express.static(getPathFromCSRDist()));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
server.listen(ssrPort, () => {
|
|
97
|
+
console.log(`ssr server start: http://localhost:${ssrPort}`);
|
|
98
|
+
cb && cb({ port: ssrPort });
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const fileCache = {};
|
|
103
|
+
function fetchFile(fileUrl) {
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
if (fileCache[fileUrl]) {
|
|
106
|
+
return resolve(fileCache[fileUrl]);
|
|
107
|
+
}
|
|
108
|
+
require('http').get(fileUrl, (res) => {
|
|
109
|
+
let fileContent = '';
|
|
110
|
+
res.on('data', (chunk) => {
|
|
111
|
+
fileContent += chunk;
|
|
112
|
+
});
|
|
113
|
+
res.on('end', () => {
|
|
114
|
+
fileCache[fileUrl] = fileContent;
|
|
115
|
+
resolve(fileContent);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@norejs/ssr-server",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "> TODO: description",
|
|
5
|
+
"author": "pengzai <roc.liu@hotmail.com>",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: run tests from root\" && exit 1",
|
|
9
|
+
"start": "node index.js"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/pengzai-dev/UniversalSSR/issues"
|
|
13
|
+
},
|
|
14
|
+
"main": "index.js",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"express": "^4.18.2",
|
|
17
|
+
"http-proxy": "^1.18.1",
|
|
18
|
+
"http-proxy-middleware": "^2.0.6",
|
|
19
|
+
"react": "16",
|
|
20
|
+
"react-dom": "16"
|
|
21
|
+
}
|
|
22
|
+
}
|