服务端加载HTML内容时的Hydration异常问题
解决Svelte中@html渲染Supabase HTML内容的 hydration 问题
问题症状
从Supabase加载的HTML内容,直接输出时显示为纯文本;用{@html}包裹后内容不显示,同时控制台出现hydration_html_changed警告。热重载(重新保存文件)后内容正常,但整页刷新时问题复现。
问题原因
Svelte的服务端渲染(SSR)与客户端hydration过程中内容不匹配:
- 服务端渲染时,
page.data.personalMessage可能尚未从Supabase获取到数据,服务端生成的DOM是空值或占位内容; - 客户端hydrate时,数据才加载完成,实际DOM内容与服务端渲染的初始DOM不一致,触发 hydration 警告,Svelte会放弃更新该节点,导致内容不显示;
- 热重载时跳过了SSR的 hydration 流程,直接在客户端渲染最新数据,所以正常显示。
解决方案
1. 用await块等待数据就绪
通过{#await}确保数据加载完成后再渲染{@html},避免服务端与客户端的内容差异:
<!-- +page.svelte --> <script> import { page } from '$app/state'; </script> <h2>Hey !</h2> <div> {#await page.data.personalMessage} <p>加载中...</p> {:then htmlContent} {@html htmlContent} {/await} </div>
2. 禁用该节点的hydration
如果服务端无法提前获取到HTML内容,直接给包裹节点添加hydrate={false}属性,让客户端完全接管该节点的渲染,跳过 hydration 校验:
<!-- +page.svelte --> <script> import { page } from '$app/state'; </script> <h2>Hey !</h2> <div> {page.data.personalMessage} <div hydrate={false}> {@html page.data.personalMessage} </div> </div>
3. 确保服务端预取数据
在+page.server.js或+page.js中提前从Supabase获取数据,保证服务端渲染时已有完整的HTML内容,让服务端与客户端的DOM完全匹配:
// +page.server.js import { supabase } from '$lib/supabase'; export async function load() { // 从Supabase获取HTML内容 const { data, error } = await supabase .from('your_table_name') .select('personalMessage') .single(); if (error) { console.error(error); return { personalMessage: '' }; } return { personalMessage: data.personalMessage }; }
内容的提问来源于stack exchange,提问作者16ar
相关产品推荐
相关产品推荐

