新项目想尽可能 ssr,结果在时区处理上翻车了

98 天前
 rocmax

服务器和 db 都是 utc ,先是统一了客户端提交的时间数据,都统一用 timestamp ,又处理了服务器和客户端渲染不一致导致的 hydration 错误。

首屏上需要显示最近一周的统计数据,可是“最近一周”是跟用户时区相关的概念,没办法在 RSC 里预先获取数据,于是翻车了。 项目开始的时候我宣传了半天 RSC 的优势,有点骑虎难下,而且 RSC 和 server action 用上后开发和用户体验都好了不少。首屏实在不想退回到 useEffect 。

现在能想到的一个办法是在 middleware 里返回给用户一个脚本,把 timezone 写到 cookie 里,再重定向到首页,之后按照 cookie 做 ssr 。

本来信心满满的用上 next14 ,server action 把 API 都淘汰掉,还挺得意的。这样一个平常的问题搞了我 2 天,郁闷死了。

1142 次点击
所在节点   Next.js
15 条回复
hingle
98 天前
时区是可以存放在“个人设置”里的(比如 v2 设置最后一行就有时区),这样就可以从数据库里拿了。
rocmax
98 天前
@hingle 感谢!
这个项目跟其他服务共用认证服务的,用户数据从 jwt 里直接取,加项目有点困难,本服务里存的话还得搞同步。

即使存到数据库里,服务端渲染解决了,dom 树叶子结点的客户端组件如果从顶层 RSC 层层传时区下来的话有点麻烦
直接从浏览器取时区的话又可能有不一致的问题。
caola
98 天前
数据统一使用 UTC ?需要显示时再转换时区?
rocmax
98 天前
@caola 现在就是这个策略,问题在于 ssr 的时候不知道客户端在哪个时区,我甚至试了获取 utc-12 到 utc+14 的所有数据,在客户端 filter 这种操作
MENGKE
97 天前
从客户端不可能拿到 100%正确的时间
rocmax
97 天前
@MENGKE 并不是追求时间正确,是用户需要看到基于当地时间的一周的数据,这就要求在 ssr 渲染之前就知道客户端的时区信息。

如果全部按照 utc 处理反而简单了。
MENGKE
97 天前
@rocmax #6 ssr 最大的目的不应该是为了 seo 和提高加载速度么,像“最近一周”这种每个用户看到的都应该是自己的和别人不一样的,我感觉完全没有做 ssr 的必要性。
rocmax
97 天前
rocmax
97 天前
@MENGKE 因为最近一周这个内容它就在首页上啊,它就是影响首屏体验,不做 ssr 就只能等着转圈圈。
rocmax
97 天前
nextjs14 开始 ssr 的优势已经不限于首屏性能和 seo ,还有 streaming 和 boundary 等等组件粒度的渲染控制,首屏以外体验也有提升。而且开发的时候因为有了 server action 我们也舍弃了笨重的 graphql 直接用 sql 了。
相对的,带来的最大缺点是需要区分服务端和客户端代码以及缓存控制。
lizy0329
97 天前
关 ssr 什么事情?拿不到时区就渲染个 404 图片,让客户端自己搞
Charrlles
97 天前
跟客户端有关的信息只能在客户端获取了吧,一味追求纯 ssr 也不太对。像时区这种都还可以存,如果是屏幕宽度之类跟客户端强相关,又不能储存的信息,岂不是懵圈了
rocmax
97 天前
最后采用的解决方法:
middleware 里判断是否存在 cookie ,不存在的话重定向到/timezone 页面,在页面中有一个 client component ,用 Intl API 获取本地 timezone ,调用 server action 设定 cookie 并重定向回之前的页面。正在尝试做 date-fns 的函数 startOf ,endOf 系列和 format 的自适应,在服务器端根据 cookie 里的时区计算,在客户端使用原函数。

考虑到用户所在时区不会经常变,将其设置了较长的过期时间。以后也可以在页面上搞个按钮来手动改这个 cookie 设定。

代价是首次访问会多跳转一次,之后没有影响。
rocmax
97 天前
解决方案受下面这篇文章启发,本来也想直接返回 html 内容,但实际用上发现客户端并不会运行其中的 js 函数,而且好像 next12 以后不让直接修改 response body 。于是采用了跳转到空页面的办法。
https://www.jacobparis.com/content/remix-ssr-dates
Belmode
97 天前
@Charrlles #12 确实是这个道理

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

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

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

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

© 2021 V2EX