Skip to content

Commit 5ac4df3

Browse files
committed
better hydration for only html tag
1 parent ce747af commit 5ac4df3

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
@@ -377,13 +377,15 @@ export default class ElementWrapper extends Wrapper {
377377

378378
const { can_use_textcontent, can_optimise_to_html_string } = this.node;
379379

380+
const to_optimise_hydration = can_optimise_to_html_string || (!is_head(parent_node) && this.node.children.length === 1 && this.node.children[0].type === 'RawMustacheTag');
381+
380382
if (hydratable) {
381383
if (parent_nodes) {
382384
block.chunks.claim.push(b`
383-
${node} = ${this.get_claim_statement(block, parent_nodes, can_optimise_to_html_string)};
385+
${node} = ${this.get_claim_statement(block, parent_nodes, to_optimise_hydration)};
384386
`);
385387

386-
if (!can_optimise_to_html_string && !this.void && this.node.children.length > 0) {
388+
if (!to_optimise_hydration && !this.void && this.node.children.length > 0) {
387389
block.chunks.claim.push(b`
388390
var ${nodes} = ${children};
389391
`);
@@ -492,7 +494,7 @@ export default class ElementWrapper extends Wrapper {
492494
this.add_styles(block);
493495
this.add_manual_style_scoping(block);
494496

495-
if (nodes && hydratable && !this.void && !can_optimise_to_html_string) {
497+
if (nodes && hydratable && !this.void && !to_optimise_hydration) {
496498
block.chunks.claim.push(
497499
b`${this.node.children.length > 0 ? nodes : children}.forEach(@detach);`
498500
);
@@ -528,7 +530,7 @@ export default class ElementWrapper extends Wrapper {
528530
return x`@element(${reference})`;
529531
}
530532

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

549-
if (can_optimise_to_html_string) {
551+
if (to_optimise_hydration) {
550552
attributes.push(p`["data-svelte"]: true`);
551553
}
552554

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import MustacheTag from '../../nodes/MustacheTag';
99
import RawMustacheTag from '../../nodes/RawMustacheTag';
1010
import { is_head } from './shared/is_head';
1111
import { Identifier, Node } from 'estree';
12+
import hash from '../../utils/hash';
1213

1314
export default class RawMustacheTagWrapper extends Tag {
1415
var: Identifier = { type: 'Identifier', name: 'raw' };
@@ -35,7 +36,7 @@ export default class RawMustacheTagWrapper extends Tag {
3536
content => insert(content)
3637
);
3738

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

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 { regex_starts_with_newline } from '../../../utils/patterns';
1212
import { Node, Expression as ESExpression } from 'estree';
13+
import hash from '../../utils/hash';
1314

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

@@ -163,9 +164,10 @@ export default function (node: Element, renderer: Renderer, options: RenderOptio
163164
if (options.hydratable) {
164165
if (options.head_id) {
165166
renderer.add_string(` data-svelte="${options.head_id}"`);
166-
}
167-
168-
if (node.can_optimise_to_html_string && !options.has_added_svelte_hash) {
167+
} else if (node.children.length === 1 && node.children[0].type === 'RawMustacheTag') {
168+
renderer.add_string(` data-svelte="${hash(JSON.stringify(node.children[0].expression.node))}"`);
169+
options = { ...options, optimised_html_hydration: true };
170+
} else if (node.can_optimise_to_html_string && !options.has_added_svelte_hash) {
169171
renderer.add_string(` data-svelte="${node.hash()}"`);
170172
options = { ...options, has_added_svelte_hash: true };
171173
}

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)