Skip to content

Commit aa8cc5d

Browse files
fix: never use html optimization for mustache tags in hydration mode (#8744)
--------- Co-authored-by: gtmnayan <[email protected]>
1 parent 3878c39 commit aa8cc5d

File tree

9 files changed

+33
-11
lines changed

9 files changed

+33
-11
lines changed

.changeset/fair-geese-repeat.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: never use html optimization for mustache tags in hydration mode

packages/svelte/src/compiler/compile/Component.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,11 +1632,9 @@ export default class Component {
16321632
unsorted_reactive_declarations.forEach(add_declaration);
16331633
}
16341634
check_if_tags_content_dynamic() {
1635-
this.tags.forEach(
1636-
/** @param {any} tag */ (tag) => {
1637-
tag.check_if_content_dynamic();
1638-
}
1639-
);
1635+
this.tags.forEach((tag) => {
1636+
tag.check_if_content_dynamic();
1637+
});
16401638
}
16411639

16421640
/**

packages/svelte/src/compiler/compile/nodes/Element.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,15 @@ export default class Element extends Node {
14641464
this.children.length > 0
14651465
);
14661466
}
1467+
get can_optimise_hydration() {
1468+
// In contrast to normal html string optimization, we also bail in case of mustache tags even
1469+
// if they seem to contain static content. This is because we cannot know whether that static
1470+
// value is different between client and server builds, e.g. {browser ? 'hi' : 'bye'} which
1471+
// becomes {'hi'} and {'bye'} respectively.
1472+
const is_static_text_content =
1473+
this.is_static_content && this.children.every((node) => node.type === 'Text');
1474+
return this.can_optimise_to_html_string && (this.can_use_innerhtml || is_static_text_content);
1475+
}
14671476
hash() {
14681477
return `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
14691478
}

packages/svelte/src/compiler/compile/render_dom/wrappers/Element/index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,13 @@ export default class ElementWrapper extends Wrapper {
458458
block.add_variable(node);
459459
const render_statement = this.get_render_statement(block);
460460
block.chunks.create.push(b`${node} = ${render_statement};`);
461-
const { can_use_textcontent, can_optimise_to_html_string } = this.node;
461+
const { can_use_textcontent, can_optimise_to_html_string, can_optimise_hydration } = this.node;
462462
if (hydratable) {
463463
if (parent_nodes) {
464464
block.chunks.claim.push(b`
465-
${node} = ${this.get_claim_statement(block, parent_nodes, can_optimise_to_html_string)};
465+
${node} = ${this.get_claim_statement(block, parent_nodes, can_optimise_hydration)};
466466
`);
467-
if (!can_optimise_to_html_string && !this.void && this.node.children.length > 0) {
467+
if (!can_optimise_hydration && !this.void && this.node.children.length > 0) {
468468
block.chunks.claim.push(b`
469469
var ${nodes} = ${children};
470470
`);
@@ -500,7 +500,7 @@ export default class ElementWrapper extends Wrapper {
500500
}
501501
// insert static children with textContent or innerHTML
502502
// skip textcontent for <template>. append nodes to TemplateElement.content instead
503-
if (can_optimise_to_html_string) {
503+
if (can_optimise_to_html_string && (!hydratable || can_optimise_hydration)) {
504504
if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
505505
/** @type {import('estree').Node} */
506506
let text = string_literal(
@@ -579,7 +579,7 @@ export default class ElementWrapper extends Wrapper {
579579
this.add_classes(block);
580580
this.add_styles(block);
581581
this.add_manual_style_scoping(block);
582-
if (nodes && hydratable && !this.void && !can_optimise_to_html_string) {
582+
if (nodes && hydratable && !this.void && !can_optimise_hydration) {
583583
block.chunks.claim.push(
584584
b`${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`
585585
);

packages/svelte/src/compiler/compile/render_ssr/handlers/Element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export default function (node, renderer, options) {
184184
}
185185
});
186186
if (options.hydratable) {
187-
if (node.can_optimise_to_html_string && !options.has_added_svelte_hash) {
187+
if (node.can_optimise_hydration && !options.has_added_svelte_hash) {
188188
renderer.add_string(` data-svelte-h="${node.hash()}"`);
189189
options = { ...options, has_added_svelte_hash: true };
190190
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Hello client!</h1>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1 data-svelte-h="svelte-1oz2hyi">Hello world!</h1>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default {
2+
snapshot(target) {
3+
return {
4+
h1: target.querySelector('h1')
5+
};
6+
}
7+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Hello {'client'}!</h1>

0 commit comments

Comments
 (0)