跳转到主文档

​使用 Loader

到目前为止,我们都是用 useEffect 来请求 BFF,加载联系人列表数据。

在启用 SSR 的情况下,useEffect 在服务器端是不会执行的,所以 SSR 过程中不会加载数据,这种 SSR 只能渲染很有限的 UI,是低价值的。

可以在当前项目中开启 SSR,看下这种效果。

"server": {
"ssr": true,
}

执行 pnpm run dev,在 devtools 的 network 面板里查看 HTML 请求的 Preview 面板,可以看到 SSR 的渲染结果只有导航栏和 Pending... 字符,并没有联系人数据:

display5

前面提到过,应用工程里的 SSR 实现是 Serverless SSR,不仅在部署、运维环节,在开发环节对 Server 也是无感的,项目里不需要专门写服务器的实现。

上述加载初始数据的业务逻辑,也不应该像传统模式一样,在客户端代码和服务器端代码中分别实现。

Modern.js 提供一个叫 useLoader 的 hooks API,在这种场景下替代 useEffect,能自动在 SSR 环节做预加载,先获取足够的数据,再运行 app 代码渲染 HTML。

同时,在 CSR 环节中,自动检查当前 loader 需要的数据,如果在 SSR 环节中已经预加载,在客户端就不再重复执行 loader,直接用现成数据;反之就在客户端执行 loader(相当于一种 fallback)。

useLoader 的使用很简单,把当前项目中 Contacts 组件中的 useEffect 代码替换成:

useLoader(
async () => {
if (!items.length && !error && !pending) {
return actions.load();
}
return Promise.resolve();
},
{
params: 'contacts',
},
);

useLoader API 要求返回一个 promise,用于判断这个 loader 是否完成。第二个参数是当前 Loader 的唯一标识。

同时,在文件顶部的导入 useLoader

import { useLoader } from '@modern-js/runtime';

重新执行 pnpm run dev,查看 view-source:http://localhost:8080/contacts/,或在 devtools 的 Network 面板里查看 HTML 请求的「 Preview 」,可以看到 SSR 渲染出来的 HTML 已经包含完整的 UI:

display6

查看 http://localhost:8080/contacts/,可以看到首屏是没有 pending 过程的。


本小节的代码可以在这里查看