SSR 项目中的运行时配置和环境变量如何设计?
简化版
SSR 项目要区分构建时配置和运行时配置。构建时配置会被打进产物,适合公开的静态值;运行时配置在服务启动或请求处理时读取,适合不同环境、不同租户、后端地址、灰度开关等。最重要的原则是:服务端密钥只能留在服务端,不能通过 HTML 注水或客户端 bundle 暴露给浏览器。
详细版
CSR 项目很多配置在 build 阶段就确定了,但 SSR 项目还有一个长期运行的服务进程,它可以在请求时读取环境变量、配置中心或请求上下文。
如果把所有配置都打包进前端代码,会导致环境切换困难、镜像复用能力差,也可能泄露密钥。更好的做法是把配置分层:公开配置给客户端,私密配置只在服务端使用,动态配置通过服务端接口或配置中心控制。
面试中要主动提“配置边界”:哪些能给客户端,哪些只能在 SSR server 内部使用。
完整版教学
一、先区分两类配置
构建时配置在打包时确定。
运行时配置在服务启动或请求过程中确定。
SSR 同时拥有浏览器 bundle 和服务端 bundle,所以配置泄露风险更高。
同一个变量名如果被错误注入客户端,可能直接出现在 JS 文件里。
二、配置分类
| 类型 | 示例 | 是否可暴露给客户端 |
|---|---|---|
| 公开配置 | CDN 地址、站点名称、公开 API base path | 可以 |
| 服务端配置 | 内网 API 地址、数据库代理地址 | 不应直接暴露 |
| 密钥配置 | OAuth secret、签名密钥、服务 token | 严禁暴露 |
| 动态开关 | 灰度策略、实验配置 | 看内容敏感度 |
三、为什么 SSR 更容易踩坑
SSR 代码可能同时被服务端和客户端引用。
如果把读取密钥的模块 import 到客户端组件,打包器可能把不该出现的内容带进产物。
有些框架用变量前缀区分公开变量和私密变量,例如 PUBLIC_ 之类。
命名规范和代码边界必须一起控制。
运行时配置的核心不是“能不能读环境变量”,而是“读到之后会不会被送到浏览器”。
这一节放到前端工程里,至少要补上一个因果链:这个选择影响什么浏览器行为,用户在慢网、重复操作或页面切换时会看到什么结果,线上又该通过什么指标发现问题。比如同样是 100 次操作,正常路径可能 95 次都成功,但剩下 5 次边界路径如果没有取消、超时、降级或清理逻辑,就会变成请求竞态、内存泄漏、白屏或安全漏洞。把这层讲清楚,小节才不是口号,而是能指导实现的判断。
四、代码示例
const serverConfig = {
internalApi: process.env.INTERNAL_API_URL,
oauthSecret: process.env.OAUTH_SECRET,
};
const publicConfig = {
cdnBase: process.env.PUBLIC_CDN_BASE,
appName: "Offer AIGC",
};
export function getPublicConfig() {
return publicConfig;
}
服务端渲染时只把 publicConfig 注水给客户端。
不要为了方便把整个 process.env 序列化到页面里。
五、多环境部署策略
开发、测试、预发、生产应该有明确配置来源。
容器镜像最好可复用,环境差异通过运行时变量注入。
前端静态资源域名如果是构建时确定,就需要每个环境重新构建。
SSR 服务地址、接口网关、灰度开关更适合运行时读取。
六、和缓存的关系
运行时配置如果参与页面内容,就会影响缓存 key。
按地区、租户、语言输出不同 HTML 时,CDN 缓存必须区分这些维度。
如果灰度开关影响 HTML,也要避免不同用户拿到错误版本。
配置不是孤立问题,它会传导到缓存和回滚策略。
七、常见误区与追问
- 误区:环境变量一定安全。 变量安全与否取决于它是否被打进客户端产物或注水到 HTML。
- 误区:SSR 里所有配置都能运行时改。 构建进 bundle 的值通常需要重新构建或重启才生效。
- 误区:公开变量前缀只是命名习惯。 在很多框架里,前缀会影响变量是否暴露到客户端。
- 追问:如何检查密钥有没有泄露? 可以扫描构建产物、HTML 注水内容和 sourcemap,同时做 secret scanning。
- 追问:配置变更需要重启吗? 环境变量通常需要重启,配置中心可做到动态刷新,但要处理一致性。
- 追问:多租户 SSR 配置怎么做? 根据 host、路径或请求头选择租户配置,并把租户维度纳入缓存设计。
八、面试表达补充
把答案落到“构建时与运行时、服务端与客户端、公开与私密、配置与缓存”四组边界。
只要边界讲清楚,说明你理解 SSR 项目不只是前端打包。
这个小节要补足可验证的场景:在 SSR 项目中的运行时配置和环境变量如何设计? 里,判断不能只停留在一句经验,而要说明触发条件、用户可见影响和工程兜底。可以把它拆成 3 步:先描述浏览器或框架实际发生了什么,再说明慢网、重复点击、页面切换或 SSR/CSR 差异会怎样放大问题,最后给出监控、降级、回滚或测试用例。这样一来,这个小节就能承担教学作用,而不是只作为结尾口号。
九、数字化小例子
以 SSR 项目中的运行时配置和环境变量如何设计? 为例,可以用 100 次用户操作做一个小推演:95 次走正常路径,4 次遇到慢网或重复触发,1 次进入异常兜底。如果代码只覆盖正常路径,本地看起来没有问题;但在线上日活放大后,这 1% 的异常就会稳定出现。
正常路径:100 × 95% = 95 次
边界路径:100 × 4% = 4 次
异常路径:100 × 1% = 1 次
结论:前端方案必须考虑弱网、重复操作和兜底
十、加强记忆
记 SSR 项目中的运行时配置和环境变量如何设计? 时,用“机制、边界、体验、兜底”四个词串起来。机制说明浏览器、运行时或框架为什么这样工作;边界说明慢网、重复点击、刷新、SSR/CSR 差异会不会出问题;体验说明它影响首屏、交互、加载还是安全;兜底说明线上失败时怎么监控、降级和回滚。这样回答既有前端工程味,也不会停留在 API 背诵。