Skip to content

Commit e03dae9

Browse files
fix: repair href attribute mismatches (#13032)
* fix: repair `href` attribute mismatches The reasoning in #9662 turns out to be false: While it's true that the href would resolve to the same URL on the initial page, once you're doing a client-side navigation to a URL at a different depth, the relative path would now point to the wrong location. Therefore we need to repair href hydration mismatches fixes sveltejs/kit#12254 * remove test * Revert "remove test" This reverts commit fa43304. * fix test * remove comment, since the rationale for skipping the attributes in question is covered by the one immediately below * fix * add test for <a> specifically --------- Co-authored-by: Rich Harris <[email protected]>
1 parent c4b7215 commit e03dae9

File tree

8 files changed

+32
-6
lines changed

8 files changed

+32
-6
lines changed

.changeset/two-cats-approve.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: repair `href` attribute mismatches

packages/svelte/src/internal/client/dom/elements/attributes.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ export function set_attribute(element, attribute, value, skip_warning) {
8989
if (hydrating) {
9090
attributes[attribute] = element.getAttribute(attribute);
9191

92-
if (attribute === 'src' || attribute === 'href' || attribute === 'srcset') {
92+
if (
93+
attribute === 'src' ||
94+
attribute === 'srcset' ||
95+
(attribute === 'href' && element.nodeName === 'LINK')
96+
) {
9397
if (!skip_warning) {
9498
check_src_in_dev_hydration(element, attribute, value);
9599
}
@@ -388,7 +392,7 @@ function check_src_in_dev_hydration(element, attribute, value) {
388392

389393
w.hydration_attribute_changed(
390394
attribute,
391-
element.outerHTML.replace(element.innerHTML, '...'),
395+
element.outerHTML.replace(element.innerHTML, element.innerHTML && '...'),
392396
String(value)
393397
);
394398
}

packages/svelte/tests/hydration/samples/ignore-mismatched-href/_config.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ export default test({
1010
},
1111

1212
test(assert, target) {
13-
assert.equal(target.querySelector('a')?.getAttribute('href'), '/bar');
13+
assert.equal(target.querySelector('link')?.getAttribute('href'), '/bar');
1414
},
1515

1616
errors: [
17-
'The `href` attribute on `<a href="/bar">...</a>` changed its value between server and client renders. The client value, `/foo`, will be ignored in favour of the server value'
17+
'The `href` attribute on `<link href="/bar">` changed its value between server and client renders. The client value, `/foo`, will be ignored in favour of the server value'
1818
]
1919
});

packages/svelte/tests/hydration/samples/ignore-mismatched-href/main.svelte

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
let { browser } = $props();
33
</script>
44

5-
<a href={browser ? '/foo': '/bar'}>foo</a>
5+
<link href={browser ? '/foo' : '/bar'} />

packages/svelte/tests/hydration/samples/img-src-mismatch/_config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ export default test({
1212
assert.htmlEqual(target.innerHTML, '<img src="server.jpg" alt="">');
1313
},
1414
errors: [
15-
'The `src` attribute on `...<img src="server.jpg" alt="">` changed its value between server and client renders. The client value, `client.jpg`, will be ignored in favour of the server value'
15+
'The `src` attribute on `<img src="server.jpg" alt="">` changed its value between server and client renders. The client value, `client.jpg`, will be ignored in favour of the server value'
1616
]
1717
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
server_props: {
5+
browser: false
6+
},
7+
8+
props: {
9+
browser: true
10+
}
11+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!--[--><a href="/foo">foo</a><!--]-->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
let { browser } = $props();
3+
</script>
4+
5+
<a href={browser ? '/foo' : '/bar'}>foo</a>

0 commit comments

Comments
 (0)