服务端渲染SSR之UmiJS预渲染

JavaScript029

服务端渲染SSR之UmiJS预渲染,第1张

本文主要介绍 UmiJS 的预渲染功能。

服务端渲染(Server-Side Rendering),是指由 服务端 完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程。

服务端渲染,首先得有后端服务器(一般是 Node.js)才可以使用,而没有后端服务器的情况下,可以使用 预渲染

预渲染与服务端渲染唯一的不同点在于 渲染时机 ,服务端渲染的时机是在用户访问时执行渲染(即实时渲染,数据一般是最新的),预渲染的时机是在项目构建时,当用户访问时,数据不一定是最新的( 如果数据没有实时性,可以直接考虑预渲染 )。

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

Umi3 在 SSR 上做了大量优化及开发体验的提升,具有以下特性:

默认情况下,服务端渲染时关闭的,可通过配置开启:

服务端渲染的数据获取方式与 SPA(单页应用) 有所不同,为了让客户端和服务端都能获取到同一份数据,Umi 提供了页面级数据的预获取。

每个页面可能有单独的数据预获取逻辑,这里我们会获取页面组件上的 getInitialProps 静态方法,执行后将结果注入到该页面组件的 props 中,如:

getInitialProps 有几个固定参数:

为了结合数据流框架,我们提供了 modifyGetInitialPropsCtx 方法,由插件或应用来扩展 ctx 参数,以 dva 为例:

然后在页面中,可以获取到 store :

同时也可以在自身应用中进行扩展:

同时可以使用 getInitialPropsCtx 将服务端参数扩展到 ctx 中,例如:

在使用的时候,就有 req 对象,不过需要注意的是,只在服务端执行时才有此参数:

则在执行 getInitialProps 方法时,除了以上两个固定参数外,还会获取到 title 和 store 参数。

关于 getInitialProps 执行逻辑和时机,需要注意:

执行 umi build ,除了正常的 umi.js 外,会多一个服务端文件: umi.server.js (相当于服务端入口文件)。然后在后端框架中,引用该文件:

render 方法参数和返回值如下:

完美兼容客户端动态加载,配置如下:

@umijs/preset-react 插件集中已内置对标题的渲染,通过以下步骤使用:

@umijs/preset-react 插件集中已内置 dva

这时候 getInitialProps(ctx) 中的 ctx 就会有 store 属性,可执行 dispatch ,并返回初始化数据。

Umi 同时支持对服务端和客户端包大小的分析

在本文中,您将学到babel,webpack,next.js, 飞冰的一些基础使用。

以及最重要的一点,不屈不挠的爬坑精神。

飞冰是什么

next.js是什么

正文开始

第一步 使用飞冰的模版创建一个项目

这里选择自定义模版,只需要它生成项目框架。

注意:这里先不要添加依赖,飞冰自己安装的webpack版本会导致next.js无法使用自身的配置启动项目。

当然,你也可以像我一样尝试,找一个酷炫的模版

然后经历如下步骤

添加依赖

npm install --save next react react-dom

安装完后,可以安装所有依赖了

npm install

安装完后,配置package.json文件,这里指定pages文件夹位于src下

到这里是不是已经迫不及待想要

npm run dev

一切看起来风和日丽,格外美丽,我们尝试显示NotFound页面

http://localhost:3000/NotFound

WTF?剧情不是这样的啊!为什么会报错,生活终于对我这只小猫咪下手了吗?

这里需要添加flie-loader来解析图片,以及sass的插件来解析scss

npm install file-loader @zeit/next-sass node-sass --save -D

然后在项目根目录新增next.js的配置文件 next.config.js

接下来继续

http://localhost:3000/NotFound

你会碰到几个 document window is undefined的错误,直接找到相应的地方增加判断

然后回到BasicNotFound.jsx中,注释飞冰使用的Link,改为a标签的href

至此,只差最后一个坑我们就能将页面展示出来了,我们需要让项目正确的识别

import IceContainer from '@icedesign/container'

我们使用babel-plugin-module-resolver插件解决

npm install --save-dev babel-plugin-module-resolver

增加.babelrc配置文件来使用该插件

至此,页面可以正确展示。

为什么明明成功展示了,却有种失败的感觉呢。