我起了Koa服务来做中间转发,配置如下:
import mount from 'koa-mount';
import path from 'path';
import { PassThrough, Stream } from 'stream';
const staticPath = path.resolve(__dirname, '../front');
let render: any;
app.use(async (ctx, next) => {
const ext = path.extname(ctx.request.path);
// 符合要求的路由才进行服务端渲染,否则走静态文件逻辑
if (!ext) {
if (!render) {
render = require(path.join(staticPath, 'umi.server.js'));
}
const { html, error, rootContainer } = await render({
basename: '/xxx/',
path: ctx.request.url,
mode: 'string',
manifest: path.join(staticPath, 'asset-manifest.json'),
});
if (error) {
console.log('----------------服务端报错-------------------', error);
ctx.throw(500, error);
} else {
ctx.status = 200;
}
if (html instanceof Stream) {
// 流渲染
ctx.type = 'application/octet-stream';
ctx.body = html.on('error', ctx.onerror).pipe(new PassThrough());
} else {
// 这里默认是字符串渲染
ctx.type = 'text/html';
ctx.body = html;
}
} else {
await next();
}
});
app.use(mount('/xxx', require('koa-static')(staticPath)));
.umirc.ts配置如下:
export default defineConfig({
define: {
ALIYUN_ID,
ALIYUN_SECRET,
},
ssr: {
devServerRender: false,
},
base: NODE_ENV === 'production' ? '/xxx/' : '/',
publicPath: NODE_ENV === 'production' ? '/xxx/' : '/',
hash: true,
antd: {},
dva: {
immer: true,
hmr: true,
},
dynamicImport: {
loading: '@/pages/Loading',
},
targets: {
ie: 11,
},
routes,
esbuild: {},
title: false,
ignoreMomentLocale: true,
manifest: {
basePath: '/',
},
fastRefresh: {},
})
本地打断点调试时遇到如下问题:
- 第一次请求会报
navigator is not defined
,再刷新一次就好了; - umi3的配置文件配置 dynamic 参数后,实际请求的资源地址没有 chunk 指纹,但 build 生成的资源是有 chunk 指纹的,导致 404;
- 由于我的资源是挂载在二级路由下的,nodejs 这边是否需要额外配置 router 的 base 参数?我暂时配了basename参数,但没在官网找到相关说明。我在.umirc中是已经配置了 base 参数的;
- 如果我希望匹配的路径进入ssr渲染,其余静态资源直接托管nginx转发,应该怎么做?即替代上述代码的koa-static处。
有没有朋友实践过umi3的ssr渲染的,指点下~
第一个问题:
遇到
window is not defined, document is not defined, navigator is not defined
类似的错误,首先全局搜索有没有在除useEffect
以外的地方使用过相关代码,如果,如果还是无法锁定,可以使用一下方式找到
umi.server.js
并用VS Code
打开该文件,点击输入报错的行号
:681726:3
,即便代码被编译过,根据前后代码的逻辑也能分析出报错对应的位置第四个问题:
umi
在ssr
渲染方面处理的还可以,路由不需要额外配置,跟客户端路由配置保持一致,静态资源托管到nginx
,这就要看以何种方式上传至 nginx 服务器,简单做法可以写nodejs
脚本实现参考文章,上传后在
.umirc
配置publicPath
指向 nginx 服务器静态资源地址目录即可,这里可以使用多环境配置策略