发布 Umi 3.2.0 — 可能是西湖区最好用的 SSR 框架

date
May 22, 2020
slug
umi3-ssr
status
Published
tags
Node.js
Web
React
summary
type
Post
 
经过近一个月、256 次提交、12 个 beta 版本后,我们发布 umi 3.2.0,增加了 服务端渲染 预渲染 功能,可能成为西湖区最好用的 SSR(服务端渲染)研发框架。
如果对 SSR(服务端渲染)不熟悉,点击查看文档,了解服务端渲染解决什么问题以及在什么场景下使用。

✨ 特性

主要具备以下特性:
  • 📦 开箱即用,只需一个配置,即可开发、部署 SSR 应用
  • 🌈 框架无关,不依赖于后端框架,可无缝运行在主流 Node.js、Serverless 框架中
  • 🚀 流式渲染,一键开启流式渲染,减少 TTFB(Time To First Byte)
  • 🔥 热更新支持,开发环境下支持代码热更新,所见即所得
  • 🎊 动态加载,支持客户端开启动态加载,对应页面输出相应资源
  • 🎁 数据预获取,Layout 支持数据预获取
  • 💄 预渲染支持,适用无后端服务器场景,预渲染在构建时将页面 HTML 生成,同时支持动态路由生成
  • ⬇️ 降级处理,服务端渲染出错后,自动降级为客户端渲染,不影响整体渲染
  • ♻️ 生态支持,插件如 dva、dumi 已支持 SSR,插件只需一个 API 即支持 SSR

快速开始

先找个地方建个空目录,并初始化一个 umi 项目,安装依赖
$ mkdir myapp && cd myapp
$ yarn create @umijs/umi-app
# 或 npx @umijs/create-umi-app
$ yarn
# 或 npm install
开启 ssr 配置,更多配置见这里
// .umirc.ts
import { defineConfig } from 'umi';

export default defineConfig({
+ ssr: {},
  nodeModulesTransform: {
    type: 'none',
  },
  routes: [{ path: '/', component: '@/pages/index' }],
});
启动项目
$ yarn start

Starting the development server...

✔ Client
  Compiled successfully in 2.75s

✔ Server
  Compiled successfully in 2.95s

 DONE  Compiled successfully in 17842ms                                       8:06:31 PM


  App running at:
  - Local:   http://localhost:8000 (copied to clipboard)
  - Network: http://192.168.12.34:8000
  
[SSR]  render / start: 69.142ms
[SSR]  render / start: 61.793ms
在浏览器里打开 http://localhost:8000/,即是服务端渲染后的页面
notion image
若需要部署,执行 umi build ,默认会生成 dist/umi.server.js ,在主流 Node.js / Serverless 框架中使用
const render = require('./dist/umi.server');
const { html, error } = await render({
  // 对应后端框架的 path/url
  // 例如 ctx.path(Koa)、req.url(Express)、ctx.request.url(Egg.js)
  path: '/',
});
例如部署在阿里云函数计算中的 Umi 3 SSR
notion image
同时提供了一个结合 eggjs 使用的 demo,更多使用见文档

性能提升

相较于 Umi 2 SSR,渲染性能近一倍提升,TTFB 是之前的一半
notion image
如果对首屏加载时间需求强烈,可开启流式渲染,减少 TTFB:
export default {
    ssr: {
    // 默认为 string
+   mode: 'stream',
  },
}

预渲染

Umi 3 没有对预渲染没有增加新配置项,只需要在 ssr  配置开启情况下,开启 exportStatic 配置即可
// .umirc.ts 
import { defineConfig } from 'umi';

export default defineConfig({
  ssr: {},
+ exportStatic: {}, 
  nodeModulesTransform: {
    type: 'none',
  },
  routes: [{ path: '/', component: '@/pages/index' }],
});
执行 umi build ,会将页面里的内容渲染到 HTML 中
$ umi build

✔ Client
  Compiled successfully in 7.35s

✔ Server
  Compiled successfully in 6.96s

INFO /index.html render success
INFO / render success

DONE  Compiled successfully in 7356ms
notion image
同时预渲染支持动态路由生成,只需要配置
export default {
    ssr: {},
    exportStatic: {
+   extraRoutePaths: async () => {
+       const ids = await request('/api/ids');
+           return ids.map(path => `/news/${id}`);
+   }
  }
}
执行 umi build 即可生成
notion image

生态支持

如果你在使用 dumi 写组件或文档,建议开启预渲染,这将有利于文档站点的 SEO、开发出来的组件库天然兼容 SSR 。
// .umirc.ts
export default {
+   ssr: {},
+   exportStatic: {},
    mode: 'site',
}
例如使用 dumi 构建的 umi 官网
notion image
对于 umi 生态中的插件集 @umijs/preset-react,已支持 dva 和 helmet 服务端渲染,这将有助于服务端应用中的数据流管理和文档头生成。
安装
$ yarn add @umijs/preset-react
dva 支持,加载 dva 插件后,会在每个 getInitialProps 函数的 ctx 参数中注入 store 参数,根据需要返回页面初始化数据
// pages/Home.tsx
const Home = () => {
    return (
    ...
  )
}

Home.getInitialProps = async (ctx) => {
    const { store } = ctx;
  return store.getState();
}
标题渲染
// pages/Home.tsx
import { Helmet } from 'umi';

export default () => (
  <>
    <Helmet>
      <title>Title Helmet</title>
    </Helmet>
  </>
)
执行渲染,HTML 中会返回渲染好的标题 title。
如果有插件需要支持 SSR,只需扩展一个运行时 API,即可支持。

反馈

可以在 umijs/umi 提交 issues,同时欢迎提交 PR

© ycjcl868 2021