Vue 3 的服务端与异步数据获取

2022-04-08 20:38:22 +08:00
 Kawa

最近项目才上线, 打算修一下 SSR 半残的状态. 以下内容是根据实践得出的结论, 不过我还是有点迷糊, 所以分享出来给大家看一下, 如果有错误或者有什么想法可以在下面指正.

内容基于使用 setup script 的情况.

几个基本点:

  1. SSR 渲染时, 生命周期钩子里只有 beforeCreate 和 created 会被触发. 意味着你不能在其他钩子里执行获取数据的逻辑.
  2. SSR 渲染时, 响应式变量不会被触发更新, 渲染状态以逻辑执行时的数据为准. 意味着如果你使用空数据占位, 等到数据到达时更新数据的做法会在 SSR 时失效.

几个建议:

  1. 如果你在用响应式变量控制组件的加载状态(isLoading), 替换成Suspense和 Async Setup. 因为isLoading不会触发组件更新, 最后即便你获取到了数据仍然可能渲染出一个骨架屏.
  2. 不要通过监听响应式变量的值变化来控制 Async Function 的挂起状态. 同样是出于响应式变量不会更新的原因, 使用响应式变量挂起和恢复 Async Function 不会起作用, 如果以这种方式去控制 Async Setup, 那么就会导致渲染死锁, 而且如果没有经验, 你几乎难以找到死锁的原因, 因为这样做在客户端是能够正常工作的, 但是在服务端是不行的.
  3. 如果你想往子组件里 Provide 你的异步数据, 请使用注入一个Ref<Promise<T>>, 而不是Ref<T | undefined>, 通过 Promise, 同样还是因为响应式变量不会触发更新, 你只能通过注入 Promise 并 await 他以挂起 setup 函数, 以确保组件被渲染时数据不为空.
1950 次点击
所在节点    Vue.js
3 条回复
duan602728596
2022-04-08 21:06:59 +08:00
SSR 时,一部分的数据(比如首屏加载的数据)是从后端获取的。
输出 html 的同时也会输出 initialData ,比如 b 站会有 window.__INITIAL_DATA__,为了保证数据的一致性,渲染不会出现差异。
通过 ajax 获取的数据本来就没有必要在后端提前获取数据,所以什么都不输出或者只渲染个骨架屏是正确的做法。
Kawa
2022-04-08 22:26:09 +08:00
@duan602728596
我做的是完全的单页应用, 所有数据都应该从后端获取.
但是这样做就非常的 SEO 不友好, 这样就得在 SSR 期间把这些数据渲染上去.
这就是你所说的 initialData.

但是你貌似没有考虑 initialData 从哪来. 对于完全的单页应用, 所有数据只能通过 API 获取, 那么我就需要考虑怎么去把这些数据搞到手并渲染出来.

我想的方案就是直接复用客户端的逻辑, 然后塞入 SSR 特有逻辑将数据打包与渲染好的内容一同发给客户端.
这种方案是我目前想到的实现成本比较低的方案, 可以直接复用客户端的逻辑获取数据.

目前还没想到实现成本更低的方案, 如果你有什么想法可以说来听听.
KouShuiYu
2022-04-20 17:53:30 +08:00
我之前的做法是按照单页应用开发,用 node 特殊处理在首页需要注入的初始变量,比如 window.__INITIAL_DATA__= 。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/845794

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX