V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rocmax
V2EX  ›  Next.js

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

  •  
  •   rocmax · 330 天前 via Android · 2224 次点击
    这是一个创建于 330 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    16 条回复    2024-08-22 20:13:22 +08:00
    hingle
        1
    hingle  
       329 天前
    时区是可以存放在“个人设置”里的(比如 v2 设置最后一行就有时区),这样就可以从数据库里拿了。
    rocmax
        2
    rocmax  
    OP
       329 天前
    @hingle 感谢!
    这个项目跟其他服务共用认证服务的,用户数据从 jwt 里直接取,加项目有点困难,本服务里存的话还得搞同步。

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

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

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

    代价是首次访问会多跳转一次,之后没有影响。
    rocmax
        14
    rocmax  
    OP
       329 天前 via Android
    解决方案受下面这篇文章启发,本来也想直接返回 html 内容,但实际用上发现客户端并不会运行其中的 js 函数,而且好像 next12 以后不让直接修改 response body 。于是采用了跳转到空页面的办法。
    https://www.jacobparis.com/content/remix-ssr-dates
    Belmode
        15
    Belmode  
       329 天前
    @Charrlles #12 确实是这个道理
    chenzhe
        16
    chenzhe  
       127 天前
    刚从 nextjs13 转到 nextjs14 的时候,脑子里对于哪些部分 server 哪些部分 client 安全是一团乱麻。
    写一阵子了稍微好一些了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2683 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 12:47 · PVG 20:47 · LAX 04:47 · JFK 07:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.