Angular NG0500水合错误原因及跳过水合方法咨询
问题描述
我正在开发采用SSR(服务器端渲染)和SSG(静态站点生成)方案的网页,有一个选择器为app-home的Home组件,其模板代码如下:
<!-- home.component.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Home Page</title> <link rel="stylesheet" href="/Users/swaroopvontela/my_portfs/src/app/home/home.component.css"> </head> <body> <header> <img src="/Users/swaroopvontela/my_portfs/src/ironP.jpg" alt="Website Logo"> <h1>Swaroop reddy vontela</h1> </header> <nav> <a href="/">Home</a> <a href="/about">About</a> <a href="/contact">Contact</a> </nav> <div class="container"> <h2>Home Page</h2> <p>web site under construction...</p> <p>looking for aws data engineer positions</p> </div> </body> </html>
执行ng serve命令后,控制台弹出NG0500错误:
[Error] ERROR – Error: NG0500: During hydration Angular expected <html> but found <meta>. Angular expected this DOM: <app-home _nghost-ng-c2925092162=""> <html lang="en">…</html> <-- AT THIS LOCATION … </app-home> Actual DOM is: <app-home _nghost-ng-c2925092162=""> <meta _ngcontent-ng-c2925092162="" charset="UTF-8">…</meta> <-- AT THIS LOCATION … </app-home> Note: attributes are only displayed to better represent the DOM but have no effect on hydration mismatches. To fix this problem: * check the "_HomeComponent" component for hydration-related issues * check to see if your template has valid HTML structure * or skip hydration by adding the `ngSkipHydration` attribute to its host node in a template Error: NG0500: During hydration Angular expected <html> but found <meta>.
我已经检查过Home组件、确认模板语法没问题,但问题还是存在,想请教三个问题:
- 这个错误到底是什么原因导致的?
- 怎么跳过水合过程?
- 宿主节点指的是什么?
问题解答
1. 错误原因
Angular做SSR/SSG水合的时候,会严格对比服务器渲染出的DOM和客户端渲染的DOM结构是否完全一致。你的问题出在:
- Home组件模板里写了完整的
<html>、<head>、<body>整套HTML文档结构,但Angular组件模板应该是页面片段,不是完整的HTML文档。 - 服务器渲染时,Angular会把
app-home组件的内容插入到项目根模板(一般是index.html)里,而浏览器不允许页面存在多个<html>标签,会自动拆解组件内的<html>、<head>,直接把<meta>这类标签提出来,导致服务器预期的DOM(app-home下直接是<html>)和客户端实际的DOM(app-home下直接是<meta>)对不上,触发了NG0500不匹配错误。
另外提一句,模板里用的绝对本地路径(比如/Users/swaroopvontela/...)不符合Angular资源引用规范,应该换成相对路径或者Angular的资产引用方式,但这不是这次报错的直接原因。
2. 跳过水合的方法
有两种简单的方式可以跳过该组件的水合:
- 方法一:在组件使用处加属性
在你写<app-home>的地方(通常是根组件模板或者路由对应的渲染位置),给这个标签加上ngSkipHydration属性:<app-home ngSkipHydration></app-home> - 方法二:在组件代码里配置
打开Home组件的ts文件,在@Component装饰器里添加host配置:@Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'], host: { 'ngSkipHydration': 'true' } }) export class HomeComponent {}
不过更建议你直接修复模板结构——把<html>、<head>、<body>这些整体结构移到项目根index.html里,Home组件只保留<header>、<nav>、<div class="container">这些页面内部内容,从根源上解决水合不匹配的问题。
3. 宿主节点的定义
在Angular里,组件的宿主节点就是你用组件选择器生成的那个DOM元素。比如你写<app-home></app-home>,这个<app-home>标签对应的DOM元素就是Home组件的宿主节点。它是组件内部模板内容的容器,组件里写的所有模板代码都会渲染到这个宿主节点的内部。
内容的提问来源于stack exchange,提问作者apopis44
相关产品推荐
相关产品推荐

