Angular 15升级至16后生产环境出现TypeError问题求助
Angular 15升级至16后生产环境报错排查方案
将Angular从15版本升级到16版本后,生产环境出现以下报错,本地开发环境无异常。项目使用了Angular Service Worker、SSR和Prismjs,已排查一周未找到根源,求解决:
main.1e8412d016703b17.js:1 ERROR TypeError: Cannot read properties of null (reading 'hasAttribute') at dc (main.1e8412d016703b17.js:1:1038118) at vM (main.1e8412d016703b17.js:1:1085062) at Tp (main.1e8412d016703b17.js:1:1084035) at Object.H_ (main.1e8412d016703b17.js:1:1084839) at template (main.1e8412d016703b17.js:1:209400) at op (main.1e8412d016703b17.js:1:1063267) at Sm (main.1e8412d016703b17.js:1:1070968) at D_ (main.1e8412d016703b17.js:1:1070856) at T_ (main.1e8412d016703b17.js:1:1071172) at Sm (main.1e8412d016703b17.js:1:1071183)
排查步骤
- 定位报错原始代码:生产环境代码已压缩,执行
ng build --configuration production --source-map生成source map,用浏览器开发者工具的Sources面板映射到原始代码,找到dc函数中调用hasAttribute的位置,确定是自有代码还是依赖库代码。 - 修复Prismjs的SSR兼容问题:Angular16对SSR流程有更新,Prismjs若在服务器端尝试操作DOM会返回null。将Prismjs初始化逻辑放到
AfterViewInit钩子,并限制仅在浏览器环境执行:import { isPlatformBrowser } from '@angular/common'; import { Inject, PLATFORM_ID } from '@angular/core'; constructor(@Inject(PLATFORM_ID) private platformId: Object) {} ngAfterViewInit() { if (isPlatformBrowser(this.platformId)) { // Prismjs初始化逻辑,如Prism.highlightAll() } } - 清理Service Worker缓存:升级后旧缓存可能导致新旧代码冲突,在
ngsw-config.json中更新version字段,或在生产环境强制用户清除Service Worker缓存。 - 检查SSR中的DOM操作:确保所有DOM操作(如
document.getElementById)都通过isPlatformBrowser判断,避免服务器端访问不存在的DOM元素。 - 更新依赖版本:执行
npm update prismjs更新Prismjs至兼容Angular16的版本,同时检查相关插件的兼容性。 - 本地模拟生产SSR:执行
ng build --configuration production && ng run [项目名]:server:production,本地启动服务器复现报错,便于调试。
内容的提问来源于stack exchange,提问作者Bunthoeurn
相关产品推荐
相关产品推荐

