Umi: SSR & Pre Rendering 方案

Created on 26 Oct 2018  ·  36Comments  ·  Source: umijs/umi

SSR

相关 ISSUE#377 #628

使用方法

首先通过 umi-plugin-ssr 插件开启 SSR 功能:

// .umirc.js

plugins: [
    ['umi-plugin-ssr', {
        // nodeExternalsWhitelist: []
        // 其他配置项待定
    }],
]

然后在服务端脚本中使用插件暴露的 express 或者 koa 中间件:

// server.js

const { render } = require('umi-plugin-ssr');
const app = require('express')();

// 启动 Umi,这里可能需要暴露 API
// 例如:umi.start();

// 使用中间件
app.use(render);

实现思路

重要的修改包括:

  • 在已有 ClientEntry 的基础上新增针对 ServerEntry 的 Webpack 构建流程,修改 target: 'node' output.libraryTarget: 'commonjs2'等等
  • 服务端预取数据。在页面组件中引入约定好的生命周期钩子。例如 Nuxt 中的 asyncData(),Next 中的 getInitialProps()
  • 使用 ReactDOMServer,将初始状态 initialState 注入 HTML
  • 在 Client 端 dva 同步初始状态 initialState,进行 hydrate()

可能遇到的问题:

  • 目前 Umi 只能通过命令启动构建,可能需要暴露可编程使用的 API
  • 在 SSR 模式下,通常我们不希望将 node_modules 中的依赖打包进 server bundle 中,因此需要使用 Webpack externals 配置项。但是在某些场景下,我们还是需要将部分特定的依赖打包进来,这时就需要使用白名单了。例如在服务端渲染场景下常常遇到的一个问题是,某些第三方依赖使用了 document, window 这样在 Node.js 环境中不存在的对象。为了保证服务端渲染正常运行,通常使用 resolve.alias 引导 Webpack 使用空的 stub 对象,此时一定要同时在 nodeExternalsWhitelist 中加入该依赖。
  • 配合 PWA 中 ServiceWorker 使用时,不同于 SPA 只有一个 HTML,不可能把每个页面都加进预缓存列表。之前在 Vue SSR 中使用 ServiceWorker 时整理了一些通用的思路。

Pre Rendering

某些 SPA 中存在一部分需要 SEO 的重要静态页面,并不需要做整站 SSR。
Pre Rendering 本身依赖于 SSR 方案,在构建时将路由静态化成为对应的 HTML 文件。

使用方法的话可以在约定/配置式路由基础上扩展。

/**
 * title: Index Page
 * prerender: true
 * Routes:
 *   - ./src/routes/a.js
 *   - ./src/routes/b.js
 */

参考资料

Nuxt 中的 PreRender
Vue SSR 中使用 ServiceWorker

type(discussion)

Most helpful comment

这几天在折腾midway和umi整合,尽快放出来一个版本

All 36 comments

关注

及时雨

https://medium.com/dev-channel/a-netflix-web-performance-case-study-c0bcde26a9d9
netflix 提到的这种方式也可以作为一个 feature

repost

关注下

Mark

关注SSR方案

ssr中间件有2种解法

1)获得res.locals.webpackStats

通过webpack-dev-server用的webpack-dev-middleware,配置

app.use(middleware(compiler, { serverSideRender: true }))

因为umi内置了webpack-dev-server,如果我能够获得webpackStats,就不需要获得webpack config

easywebpack使用的就是这种方式实现的。其实就是webpack-dev-server将webpackStats抛出来,你自己的web server收到webpackStats(http、rpc、ws都行),其他过程就一样了。easywebpack采用的egg的agent实现的,可圈可点吧

如果大家想挑战一下,也可以试试

2)通过代码去获取webpack config。

原理跟umi inspect原理一样。

// 获取webpack配置信息
const webpackConfig = require('umi-build-dev/lib/getWebpackConfig').default(service);

const compiler = webpack(webpackConfig);

// 测试webpack执行情况
compiler.run((err, stats) => {/* ...处理结果 */
if (err) console.dir(err)

console.dir(stats)
})

通过这种方法能够取到compiler,已实现,参见https://github.com/i5ting/get-umi-webpack-compiler

+1

Pre Rendering 对于 h5 和静态 landing 站点的 SEO 和性能意义巨大。

同构最麻烦的一点就是数据在页面上是 double 的,一份是原 json 数据,一份是渲染好的数据。

有没有支持的时间节点呢?

+1 Watching,Pre Rendering 能满足大部分对外站点,可参照 gatsby

image

mark

强烈的需求啊

这几天在折腾midway和umi整合,尽快放出来一个版本

@i5ting 狼叔有实现umi的SSR嘛?

保持关注

👍

关注着

期待 umi ssr 啊

求umi整合SSR的demo

两个月过去了,有什么音信没

@furylee 已经实现了,pr在内部review

@i5ting 狼叔威武 等待体验ing....

关注

快点出吧 next.js缺陷很多啊

预计什么时候放出来呢?很需要ssr

期待ssr

mark
内部review中

关注中,希望早点放出来。狼叔牛批

mark,期待中

mark

mark

mark

期待ing,狼叔威武

@philina 已经发布了
docs: https://umijs.org/docs/ssr

Was this page helpful?
0 / 5 - 0 ratings