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

服务端渲染(SSR)怎么区分 JS 代码块是在浏览器执行,还是在 Server 端执行?

  •  
  •   legstrong · 2021-08-31 16:15:32 +08:00 · 1853 次点击
    这是一个创建于 940 天前的主题,其中的信息可能已经有所发展或是发生改变。

    刚开始看前端框架,对服务端渲染(SSR)很感兴趣。 想问一下哪位仁兄能否解答一下这个问题,在启动 SSR 后

    npm run dev:ssr
    

    Angular 是怎么区分哪一部分的 JS 在浏览器端执行,哪一部分在 Server 端执行的?

    很可能是我作为后端程序员对 SSR 的认识存在偏颇。多多指教!

    8 条回复    2023-04-26 01:02:29 +08:00
    shapl
        1
    shapl  
       2021-08-31 16:21:49 +08:00
    生命周期钩子 ?
    acthtml
        2
    acthtml  
       2021-08-31 16:31:27 +08:00
    可以通过 window 对象来简单不严谨区分:在 server 端,没有这个 window 对象。

    如果要严谨,需要参考具体 ssr 的实现文档,一般会有入口类型这样的全局常量,例如 WEBPACK_ENTRY_TYPE == 'server'.
    blurh11E27
        3
    blurh11E27  
       2021-08-31 17:45:19 +08:00
    唉 研究完了 找我做项目呀 哈哈哈哈
    zlgodpig
        4
    zlgodpig  
       2021-08-31 18:09:24 +08:00
    1. runtime 判断。node 和 浏览器有不同的 global 对象。不过这个可以 mock,还是要自己检查下
    2. build 两个版本,build 的时候加构建参数。
    duan602728596
        5
    duan602728596  
       2021-08-31 19:03:24 +08:00
    一般来说,服务端不存在 window 和 document,所以可以通过
    typeof window === 'undefined'
    typeof document === 'undefined'
    来判断。而且对于组件尤其要注意当前的环境
    lujjjh
        6
    lujjjh  
       2021-08-31 20:41:49 +08:00
    “Angular 是怎么区分哪一部分的 JS 在浏览器端执行,哪一部分在 Server 端执行的?”

    我觉得你想要问的是一段代码比如 t = Date.now(),Angular 怎么确定它应该在服务端执行,还是交给浏览器执行。(远古时期的“SSR”是在 <script> 上标明 [runat="server"] :doge )

    SSR 一般只渲染初始状态,所以可以认为服务端只执行渲染初始状态所必须执行的代码。至于 Angular 具体是什么策略,我没有写过 Angular,所以没法回答,但肯定是只要按照 Angular 的约定写代码,Angular 会自动帮你处理好 SSR 。

    在服务端执行和在浏览器端执行也不是相交的,一段代码可能在首次渲染和后续渲染的时候都需要执行,所以 SSR 的代码需要同构(既能在服务端跑,又能在浏览器跑),除了一些常规的 HTTP 库,看起来 Angular 还在服务端实现了一套 document 和 location 的接口。
    legstrong
        7
    legstrong  
    OP
       2021-09-01 15:57:05 +08:00
    感谢各位的回复!

    > 我觉得你想要问的是一段代码比如 t = Date.now(),Angular 怎么确定它应该在服务端执行,还是交给浏览器执行。(远古时期的“SSR”是在 <script> 上标明 [runat="server"] :doge )

    @lujjjh 是的,我需要知道这个。
    Angular 的目录结构看起来像是把这部分的代码揉在了一起。

    需要进一步了解是担心机密信息、加密规则暴露在浏览器端。

    我再研究一下,有结果了会跟大家分享。
    fuyun
        8
    fuyun  
       338 天前
    import { isPlatformBrowser } from '@angular/common';
    import { Inject, Injectable, PLATFORM_ID } from '@angular/core';

    @Injectable({
    providedIn: 'root'
    })
    export class PlatformService {
    isBrowser = this.platformId ? isPlatformBrowser(this.platformId) : typeof document === 'object' && !!document;

    constructor(@Inject(PLATFORM_ID) private platformId: any) {}
    }
    调用:
    if (!this.platform.isBrowser) {
    ...
    }
    另外,机密信息、加密规则建议放在服务端,通过接口去调用。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   953 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:39 · PVG 05:39 · LAX 14:39 · JFK 17:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.