# 服务端渲染(SSR)

Support in 2.8.0+

# 介绍

# 什么是服务端渲染

服务端渲染(Server-Side Render),是指将单页应用(SPA)在服务器端渲染为 HTML 片段,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程。

uml diagram

# 与客户端渲染的区别

后续简称服务端渲染为 SSR,客户端渲染为 CSR

如下图所示:

uml diagram

SSR 优势在于:

  • 更友好的 SEO:爬虫可以直接抓取渲染之后的页面,CSR 首次返回的 HTML 文档中,是空节点(root),不包含内容。而 SSR 返回渲染之后的 HTML 片段,内容完整,所以能更好地被爬虫分析与索引。
  • 更快的首屏加载速度:无需等待 JavaScript 完成下载且执行才显示内容,更快速地看到完整渲染的页面。有更好的用户体验。
  • 需要服务端支持:Umijs 主要关注是应用 UI 层渲染,完成 SSR 需要服务端(例如:Node.js)支持。

# Umi SSR 特性

  • 服务端框架无关
  • 支持 CSS Modules
  • 支持 TypeScript
  • 支持本地开发 HMR
  • 支持 dva
  • 支持 Serverless

# 使用

# Umi 配置

配置文件开启 ssr: true更多配置

export default {
  ssr: true,
};

开启后,运行 umi build,会生成如下文件:

.
├── dist
│   ├── index.html
│   ├── ssr-client-mainifest.json
│   ├── umi.css
│   ├── umi.js
│   └── umi.server.js

# 服务端

由于与服务端框架无关,Umi 关注是应用 UI 层渲染,与服务端框架不耦合。

为了降低服务端框架接入门槛,Umi 提供 umi-server,并以常见的 Node.js 服务端框架(KoajsExpressEgg.js)为例,给出具体接入方式。

# 使用原生 http 模块

用 Node.js 原生 http 模块做服务端渲染。

// bar.js
const server = require('umi-server');
const http = require('http');
const { createReadStream } = require('fs');
const { join, extname } = require('path');

const root = join(__dirname, 'dist');
const render = server({
  root,
})
const headerMap = {
  '.js': 'text/javascript',
  '.css': 'text/css',
  '.jpg': 'image/jpeg',
  '.png': 'image/jpeg',
}

http.createServer(async (req, res) => {
  const ext = extname(req.url);
  const header = {
    'Content-Type': headerMap[ext] || 'text/html'
  }
  res.writeHead(200, header);

  if (!ext) {
    // url render
    const ctx = {
      req,
      res,
    }
    const { ssrHtml } = await render(ctx);
    res.write(ssrHtml);
    res.end()
  } else {
    // static file url
    const path = join(root, req.url);
    const stream = createReadStream(path);
    stream.on('error', (error) => {
      res.writeHead(404, 'Not Found');
      res.end();
    });
    stream.pipe(res);
  }

}).listen(3000)

console.log('http://localhost:3000');

运行 node bar.js,访问 http://localhost:3000,就是一个简单的服务端渲染例子。详细可见 examples/normal

image

# Koa.js

可参考 examples/koajs

# Egg.js

可参考 examples/eggjs

# 预渲染(Pre Render)

预渲染(Pre Render)在构建时执行渲染,将渲染后的 HTML 片段生成静态 html 文件。无需使用 web 服务器实时动态编译 HTML,适用于静态站点

Umi 提供 @umijs/plugin-prerender 插件,帮助用户在构建时预渲染出页面。更多用法参考文档

export default {
  plugins: [['@umijs/plugin-prerender', options]],
};

# 常见问题

FAQ