Skip to content

Commit 563fc88

Browse files
committed
better hydration for only html tag
1 parent 5466925 commit 563fc88

File tree

8 files changed

+39
-13
lines changed

8 files changed

+39
-13
lines changed

src/compiler/compile/render_dom/wrappers/Element/index.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,15 @@ export default class ElementWrapper extends Wrapper {
363363

364364
const { can_use_textcontent, can_optimise_to_html_string } = this.node;
365365

366+
const to_optimise_hydration = can_optimise_to_html_string || (!is_head(parent_node) && this.node.children.length === 1 && this.node.children[0].type === 'RawMustacheTag');
367+
366368
if (hydratable) {
367369
if (parent_nodes) {
368370
block.chunks.claim.push(b`
369-
${node} = ${this.get_claim_statement(block, parent_nodes, can_optimise_to_html_string)};
371+
${node} = ${this.get_claim_statement(block, parent_nodes, to_optimise_hydration)};
370372
`);
371373

372-
if (!can_optimise_to_html_string && !this.void && this.node.children.length > 0) {
374+
if (!to_optimise_hydration && !this.void && this.node.children.length > 0) {
373375
block.chunks.claim.push(b`
374376
var ${nodes} = ${children};
375377
`);
@@ -477,7 +479,7 @@ export default class ElementWrapper extends Wrapper {
477479
this.add_styles(block);
478480
this.add_manual_style_scoping(block);
479481

480-
if (nodes && hydratable && !this.void && !can_optimise_to_html_string) {
482+
if (nodes && hydratable && !this.void && !to_optimise_hydration) {
481483
block.chunks.claim.push(
482484
b`${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`
483485
);
@@ -513,7 +515,7 @@ export default class ElementWrapper extends Wrapper {
513515
return x`@element(${reference})`;
514516
}
515517

516-
get_claim_statement(block: Block, nodes: Identifier, can_optimise_to_html_string: boolean) {
518+
get_claim_statement(block: Block, nodes: Identifier, to_optimise_hydration: boolean) {
517519
const attributes = this.attributes
518520
.filter((attr) => !(attr instanceof SpreadAttributeWrapper) && !attr.property_name)
519521
.map((attr) => p`${(attr as StyleAttributeWrapper | AttributeWrapper).name}: true`);
@@ -531,7 +533,7 @@ export default class ElementWrapper extends Wrapper {
531533
reference = x`(${this.node.tag_expr.manipulate(block)} || 'null').toUpperCase()`;
532534
}
533535

534-
if (can_optimise_to_html_string) {
536+
if (to_optimise_hydration) {
535537
attributes.push(p`["data-svelte"]: true`);
536538
}
537539

src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import MustacheTag from '../../nodes/MustacheTag';
77
import RawMustacheTag from '../../nodes/RawMustacheTag';
88
import { is_head } from './shared/is_head';
99
import { Identifier } from 'estree';
10+
import hash from '../../utils/hash';
1011

1112
export default class RawMustacheTagWrapper extends Tag {
1213
var: Identifier = { type: 'Identifier', name: 'raw' };
@@ -33,7 +34,7 @@ export default class RawMustacheTagWrapper extends Tag {
3334
content => insert(content)
3435
);
3536

36-
block.chunks.mount.push(insert(init));
37+
block.chunks.mount.push(b`if (@get_svelte_dataset(${parent_node}) !== "${hash(JSON.stringify(this.node.expression.node))}") ${insert(init)}`);
3738
} else {
3839
const needs_anchor = in_head || (this.next ? !this.next.is_dom_node() : (!this.parent || !this.parent.is_dom_node()));
3940

src/compiler/compile/render_ssr/Renderer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export interface RenderOptions extends CompileOptions{
4747
locate: (c: number) => { line: number; column: number };
4848
head_id?: string;
4949
has_added_svelte_hash?: boolean;
50+
optimised_html_hydration?: boolean;
5051
}
5152

5253
export default class Renderer {

src/compiler/compile/render_ssr/handlers/Element.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import fix_attribute_casing from '../../render_dom/wrappers/Element/fix_attribut
1010
import { namespaces } from '../../../utils/namespaces';
1111
import { start_newline } from '../../../utils/patterns';
1212
import { Expression as ESExpression } from 'estree';
13+
import hash from '../../utils/hash';
1314

1415
export default function (node: Element, renderer: Renderer, options: RenderOptions) {
1516

@@ -156,9 +157,10 @@ export default function (node: Element, renderer: Renderer, options: RenderOptio
156157
if (options.hydratable) {
157158
if (options.head_id) {
158159
renderer.add_string(` data-svelte="${options.head_id}"`);
159-
}
160-
161-
if (node.can_optimise_to_html_string && !options.has_added_svelte_hash) {
160+
} else if (node.children.length === 1 && node.children[0].type === 'RawMustacheTag') {
161+
renderer.add_string(` data-svelte="${hash(JSON.stringify(node.children[0].expression.node))}"`);
162+
options = { ...options, optimised_html_hydration: true };
163+
} else if (node.can_optimise_to_html_string && !options.has_added_svelte_hash) {
162164
renderer.add_string(` data-svelte="${node.hash()}"`);
163165
options = { ...options, has_added_svelte_hash: true };
164166
}

src/compiler/compile/render_ssr/handlers/HtmlTag.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import RawMustacheTag from '../../nodes/RawMustacheTag';
33
import { Expression } from 'estree';
44

55
export default function(node: RawMustacheTag, renderer: Renderer, options: RenderOptions) {
6-
if (options.hydratable) renderer.add_string('<!-- HTML_TAG_START -->');
6+
if (options.hydratable && !options.optimised_html_hydration) renderer.add_string('<!-- HTML_TAG_START -->');
77
renderer.add_expression(node.expression.node as Expression);
8-
if (options.hydratable) renderer.add_string('<!-- HTML_TAG_END -->');
8+
if (options.hydratable && !options.optimised_html_hydration) renderer.add_string('<!-- HTML_TAG_END -->');
99
}

test/runtime/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ describe('runtime', () => {
154154
window.SvelteComponent = SvelteComponent;
155155

156156
const target = window.document.querySelector('main');
157+
let snapshot = undefined;
157158

158159
if (hydrate && from_ssr_html) {
159160
// ssr into target
@@ -163,6 +164,11 @@ describe('runtime', () => {
163164
const SsrSvelteComponent = require(`./samples/${dir}/main.svelte`).default;
164165
const { html } = SsrSvelteComponent.render(config.props);
165166
target.innerHTML = html;
167+
168+
if (config.snapshot) {
169+
snapshot = config.snapshot(target);
170+
}
171+
166172
delete compileOptions.generate;
167173
if (config.after_test) config.after_test();
168174
} else {
@@ -212,6 +218,7 @@ describe('runtime', () => {
212218
component,
213219
mod,
214220
target,
221+
snapshot,
215222
window,
216223
raf,
217224
compileOptions

test/runtime/samples/raw-anchor-first-last-child/_config.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,24 @@ export default {
33
raw: '<span>foo</span>'
44
},
55

6-
test({ assert, component, target }) {
6+
snapshot(target) {
7+
const span = target.querySelector('span');
8+
9+
return {
10+
span
11+
};
12+
},
13+
14+
test({ assert, component, target, snapshot }) {
715
const span = target.querySelector('span');
816
assert.ok(!span.previousSibling);
917
assert.ok(!span.nextSibling);
1018

19+
if (snapshot) {
20+
assert.equal(span, snapshot.span);
21+
}
22+
1123
component.raw = '<span>bar</span>';
24+
assert.htmlEqual(target.innerHTML, '<div><span>bar</span></div>');
1225
}
1326
};

test/runtime/samples/raw-mustaches-preserved/_config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default {
1111
const p = target.querySelector('p');
1212

1313
component.raw = '<p>does not change</p>';
14-
assert.equal(target.innerHTML, '<div><p>does not change</p></div>');
14+
assert.htmlEqual(target.innerHTML, '<div><p>does not change</p></div>');
1515
assert.strictEqual(target.querySelector('p'), p);
1616
}
1717
};

0 commit comments

Comments
 (0)