Spartacus 3.0 SSR下导入AuthService配置OAuth redirectUri的报错
TypeError: Cannot read property 'location' of undefined的本质是SSR运行的Node.js环境不存在浏览器端原生window全局对象,而Spartacus 3.0内置的OAuthLibWrapperService在初始化阶段,会直接读取window.location的属性值来解析配置的redirectUri参数,当服务端执行这段初始化逻辑时,访问undefined对象上的location属性就会抛出类型错误。
报错触发逻辑完全匹配实际观察到的现象:
- 移除所有AuthService相关导入时,依赖注入链不会触发
OAuthLibWrapperService、AsmAuthService的实例化流程,不会走到读取window属性的代码分支 - 保留AuthService导入但移除
OAuthLibConfig中的redirectUri参数时,服务初始化逻辑会跳过依赖window.location的URL拼接校验,因此不会触发报错
第一步:在SSR服务入口补全最小化的全局window mock
打开项目中的SSR服务入口文件(通常为项目根目录下的server.ts),在Express实例、Angular应用引擎初始化前,为Node运行时注入OAuth服务需要的最小window对象,不需要引入完整的浏览器API mock库,仅覆盖当前报错涉及的属性即可:// server.ts 文件头部,在服务初始化逻辑前添加 if (typeof window === 'undefined') { global.window = { location: { origin: 'https://your-production-domain.com', // 替换为业务实际的站点域名 href: 'https://your-production-domain.com', pathname: '/' } }; }这段逻辑仅在服务端运行时生效,不会覆盖客户端浏览器环境的原生window对象,也不会影响客户端侧的运行逻辑。
第二步:优化redirectUri配置的环境适配逻辑
不要在静态配置中硬编码依赖运行时window解析的redirectUri值,通过平台判断、服务端请求令牌动态拼接不同运行环境下的正确地址:// 在Spartacus配置的工厂函数中添加环境判断逻辑 provide: OAuthLibConfig, useFactory: (platformId: any, serverRequest: any) => { const baseUrl = isPlatformBrowser(platformId) ? window.location.origin : `${serverRequest.protocol}://${serverRequest.get('host')}`; return { redirectUri: `${baseUrl}/login/callback` // 保留业务需要的redirectUri配置 }; }, deps: [PLATFORM_ID, SERVER_REQUEST]第三步:调整服务初始化时机,避免SSR阶段过早实例化浏览器依赖服务
按照Spartacus 3.0的模块规范,将AuthService相关的导入从根AppModule迁移到业务路由的懒加载模块中,避免应用初始化阶段(SSR执行过程中)就触发需要浏览器API的服务实例化,减少不必要的服务端API兼容成本。
- 执行
yarn build:ssr重新完成SSR构建 - 执行
yarn dev:ssr启动本地SSR服务 - 访问应用主页确认报错消失,同时浏览器端OAuth登录流程的redirectUri跳转逻辑保持正常,符合业务预期。
内容的提问来源于stack exchange,提问作者Mirosław Grochowski

