umijs 服务端渲染(SSR) 指南

2024-06-06 13:04

本文主要是介绍umijs 服务端渲染(SSR) 指南,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

umijs 服务端渲染(SSR) 指南

Umi 是什么?

Umi,中文可发音为乌米,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。

Umi 是蚂蚁集团的底层前端框架,已直接或间接地服务了 3000+ 应用,包括 java、node、H5 无线、离线(Hybrid)应用、纯前端 assets 应用、CMS 应用等。他已经很好地服务了我们的内部用户,同时希望他也能服务好外部用户。

选择umijs v3版本

umijs v4版本已经发布,但是ssr功能还不完善,所以建议使用v3版本。

https://v3.umijs.org/zh-CN/docs/ssr

创建项目

mkdir umi-ssr-demo
cd umi-ssr-demo
npx @umijs/create-umi-app
npm i
npm run start

配置

    1. 配置 .umirc.js
import { defineConfig } from 'umi';export default defineConfig({nodeModulesTransform: {type: 'none',},routes: [{ path: '/', component: '@/pages/index' },],fastRefresh: {},/** 开启ssr */ssr: {}
});
    1. 查看是否开启成功

20240606112924

如上图所示,直接返回了dom,不止一个根节点,这就算成功了

页面title、meta

每个页面都可以配置title和meta,通过配置<Helmet>组件即可

import React from 'react';
import { Helmet } from 'umi';export default () => {return (<>{/* 可自定义需不需要编码 */}<Helmet><title>Hello Umi Bar Title</title><metaname="keywords"content="Hello Umi Bar Title"/><metaname="description"content="Hello Umi Bar Title"/></Helmet></>);
};

获取接口数据

可以直接使用 umi-request 像spa应用一样获取接口数据,但是服务端渲染的,我们需要再服务器返回前就把数据获取好

每个页面有getInitialProps方法,在这个方法里可以获取数据,只有页面才有,组件是没有的

import React from 'react';const Home = (props) => {const { data } = props;return ({/* <div>Hello World</div> */}<div>{data.title}</div>)
}Home.getInitialProps = (async (ctx) => {return Promise.resolve({data: {title: 'Hello World',}})
})

当一个页面请求多个接口时,可以使用Promise.all()合并数据,能使请求速度变快,多个请求同时发出,而不是链式获取

import React from 'react';const Home = (props) => {const { data } = props;return ({/* <div>Hello World</div> */}<div>{data.title}</div>)
}Home.getInitialProps = (async (ctx) => {const [res1, res2] = await Promise.all([/** */])return {res1,res2}
})

当数据量大了之后,会导致直接卡住,比如分页接口,调整了pageSize参数过大,可能导致页面卡死,可以将接口分片成多个请求,然后合并数据

export const useFiberRequest = async (fn, parames) => {const { page = 1, page_size = 10 } = parames?.pagination || {};const fiberSize = 10;const promiseList: any[] = [];for (let p = 1; p <= page_size / fiberSize; p++) {const pagination = {page: (page - 1) * (page_size / fiberSize) + p,page_size: fiberSize,};promiseList.push(fn({...parames,pagination,}),);}const resList: any[] = await Promise.all(promiseList);const list = resList?.map((item) => item?.data?.list);const total = resList?.[0]?.data?.total || 0;return {data: {list: list?.flat(),total,},};
};

富文本

只有 div 标签 dangerouslySetInnerHTML 属性才能被 SSR 渲染,正常的写法应该是:

- <p dangerouslySetInnerHTML={{ __html: '<p>Hello</p>' }} />
+ <div dangerouslySetInnerHTML={{ __html: '<p>Hello</p>' }} />

与 dva 结合使用

已内置 dva,通过以下步骤使用:

    1. 配置.umirc.ts开启
export default {dva: {}
}

使用antd v5

由于antd v5是css in js的形式,所以样式是异步导入,导致ssr渲染时会先渲染出接口,然后闪一下,才加载出样式

我们可以把antd v5的样式提前加载,在ssr渲染时,先渲染出样式,然后再渲染出结构

  • 安装包
npm i -D @ant-design/static-style-extract ts-node cross-env
  • 生成antd v5 样式脚本
// src/scripts/genAntdCss.tsx
import { extractStyle } from '@ant-design/static-style-extract';
import fs from 'fs';const outputPath = './public/css/antd.min.css';// 1. default themeconst css = extractStyle();// 2. With custom theme// const css = extractStyle(withTheme);fs.writeFileSync(outputPath, css);console.log(`🎉 Antd CSS generated at ${outputPath}`);
  • 在package.json中添加脚本
{"scripts": {"predev": "ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx","prebuild": "cross-env NODE_ENV=production ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx",}
}
  • 在app.tsx中引入
import '../public/css/antd.min.css';

部署

需要再起一个node服务,然后将ssr生成的dist目录作为静态资源目录

var Koa = require('koa'),logger = require('koa-logger'),json = require('koa-json'),views = require('koa-views'),onerror = require('koa-onerror');
const { extname } = require('path');const app = new Koa();// error handler
onerror(app);let render;
app.use(async (ctx, next) => {const req = ctx.req;const res = ctx.res;const ext = extname(ctx.request.path);if (ext) {await next();return;}// 或者从 CDN 上下载到 server 端// const serverPath = await downloadServerBundle('http://cdn.com/bar/umi.server.js');if (!render) {render = require('./dist/umi.server');}res.setHeader('Content-Type', 'text/html');const context = {};const { html, error, rootContainer } = await render({// 有需要可带上 querypath: req.url,context,// 可自定义 html 模板// htmlTemplate: defaultHtml,// 启用流式渲染// mode: 'stream',// html 片段静态标记(适用于静态站点生成)// staticMarkup: false,// 扩展 getInitialProps 在服务端渲染中的参数// getInitialPropsCtx: {},// manifest,正常情况下不需要});if (error) {console.log('----------------服务端报错-------------------', error);ctx.throw(500, error);}ctx.body = html;
});// global middlewares
app.use(views('views', {root: __dirname + '/views',default: 'jade',}),
);
app.use(require('koa-bodyparser')());
app.use(json());
app.use(logger());app.use(function* (next) {var start = new Date();yield next;var ms = new Date() - start;console.log('%s %s - %s', this.method, this.url, ms);
});app.use(require('koa-static')(__dirname + '/dist'));// error-handling
app.on('error', (err, ctx) => {console.error('server error', err, ctx);
});module.exports = app;

运行node服务,将ssr生成的dist目录替换服务中的dist目录即可

这篇关于umijs 服务端渲染(SSR) 指南的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1036182

相关文章

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON:

深入浅出SpringBoot WebSocket构建实时应用全面指南

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS... 目录前言为什么需要 WebSocketWebSocket 是什么Spring Boot 如何简化 We

Python极速搭建局域网文件共享服务器完整指南

《Python极速搭建局域网文件共享服务器完整指南》在办公室或家庭局域网中快速共享文件时,许多人会选择第三方工具或云存储服务,但这些方案往往存在隐私泄露风险或需要复杂配置,下面我们就来看看如何使用Py... 目录一、android基础版:HTTP文件共享的魔法命令1. 一行代码启动HTTP服务器2. 关键参

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Redis MCP 安装与配置指南

《RedisMCP安装与配置指南》本文将详细介绍如何安装和配置RedisMCP,包括快速启动、源码安装、Docker安装、以及相关的配置参数和环境变量设置,感兴趣的朋友一起看看吧... 目录一、Redis MCP 简介二、安www.chinasem.cn装 Redis MCP 服务2.1 快速启动(推荐)2.

OpenCV在Java中的完整集成指南分享

《OpenCV在Java中的完整集成指南分享》本文详解了在Java中集成OpenCV的方法,涵盖jar包导入、dll配置、JNI路径设置及跨平台兼容性处理,提供了图像处理、特征检测、实时视频分析等应用... 目录1. OpenCV简介与应用领域1.1 OpenCV的诞生与发展1.2 OpenCV的应用领域2

MyBatis-Plus 自动赋值实体字段最佳实践指南

《MyBatis-Plus自动赋值实体字段最佳实践指南》MyBatis-Plus通过@TableField注解与填充策略,实现时间戳、用户信息、逻辑删除等字段的自动填充,减少手动赋值,提升开发效率与... 目录1. MyBATis-Plus 自动赋值概述1.1 适用场景1.2 自动填充的原理1.3 填充策略