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

相关文章

python中各种常见文件的读写操作与类型转换详细指南

《python中各种常见文件的读写操作与类型转换详细指南》这篇文章主要为大家详细介绍了python中各种常见文件(txt,xls,csv,sql,二进制文件)的读写操作与类型转换,感兴趣的小伙伴可以跟... 目录1.文件txt读写标准用法1.1写入文件1.2读取文件2. 二进制文件读取3. 大文件读取3.1

SpringBoot中配置Redis连接池的完整指南

《SpringBoot中配置Redis连接池的完整指南》这篇文章主要为大家详细介绍了SpringBoot中配置Redis连接池的完整指南,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以... 目录一、添加依赖二、配置 Redis 连接池三、测试 Redis 操作四、完整示例代码(一)pom.

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

PyInstaller打包selenium-wire过程中常见问题和解决指南

《PyInstaller打包selenium-wire过程中常见问题和解决指南》常用的打包工具PyInstaller能将Python项目打包成单个可执行文件,但也会因为兼容性问题和路径管理而出现各种运... 目录前言1. 背景2. 可能遇到的问题概述3. PyInstaller 打包步骤及参数配置4. 依赖

Nginx中配置HTTP/2协议的详细指南

《Nginx中配置HTTP/2协议的详细指南》HTTP/2是HTTP协议的下一代版本,旨在提高性能、减少延迟并优化现代网络环境中的通信效率,本文将为大家介绍Nginx配置HTTP/2协议想详细步骤,需... 目录一、HTTP/2 协议概述1.HTTP/22. HTTP/2 的核心特性3. HTTP/2 的优

在React中引入Tailwind CSS的完整指南

《在React中引入TailwindCSS的完整指南》在现代前端开发中,使用UI库可以显著提高开发效率,TailwindCSS是一个功能类优先的CSS框架,本文将详细介绍如何在Reac... 目录前言一、Tailwind css 简介二、创建 React 项目使用 Create React App 创建项目

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4