Svelte parses HTML all wrongについてまとめる
このスクラップはSvelteのIssue「Svelte parses HTML all wrong」の議論を見守るスクラップ
自分用にまとめていきますが認識違う箇所があればコメントいただけると助かります
そもそもの事と起点としては「Don't self-close void elements, because invalid when using HTML5」というIssue
SvelteKitがHTML5 doc typeを使用しているため、W3C ValidatorがビルドされたHTMLに対して警告が出る
具体的にはmeta
やlink
といった空要素に終了タグが加わっていることで警告が入っている
関連する箇所は以下のコード部分
Prettierによる整形の影響で閉じタグが付いてしまっているため、RichによってSvelteによる問題ではないことが判明できた
ただこの件によりSvelteが空要素のself-closingに対して誤って解釈されている問題についてを知るきっかけになった
Richは下記のようなdiv要素自体に閉じタグを付ける場合
<div />
以下のようなショートハンドになると思っていた
<div></div>
しかしHTML自体には自己完結型タグというものは存在しないため、以下のようなコードは
<div />こんにちは!
閉じタグは無視されて以下のように判定される
<div>こんにちは!</div>
このHTMLの振る舞いとSvelteの解析を比較すると、Svelteは誤った解釈をしていたことがわかった
ref: https://github.com/sveltejs/svelte/issues/11052#issue-2223254077
本来はSelf-closingな空要素を許可しないことになる(これはHTMLにのみ適用され、他の名前空間には適用されない)
これを許可しないことになるのは大きな変更になるが、代替案を用意する
- 現状の間違ったHTMLの解析を続ける
- HTMLを正しく解析し、
<div />
を<div></div>
として扱う。破壊的な変更だけど、デバッグするのは悪夢のようだ
理想的には、Self-closingな空要素(つまり <input>
ではなく <input />
な要素)も禁止したいところだが、これが現実的かどうかは、空要素に不要な />
を追加する Prettier の現在の挙動においてそれを妨げるかどうかによる
ref: https://github.com/sveltejs/svelte/issues/11052#issue-2223254077
以下のようなSvelteコンポーネントにおいては
<script>
import { onMount } from 'svelte';
let div;
onMount(() => {
console.log(div.textContent);
});
</script>
<div bind:this={div} />hello!
1番目のケースは'hello!' がログに記録されて、2番目のケースでは、空の文字列がログに記録されるようになる
Prettierでは現在空要素に対してSelf-closingを自動的に付与するようになっており、そのこと自体を解除するようなオプションは現在設定されていない
Svelteの既存の振る舞いを変える可能性があることに賛同しない人もいるが、Rich曰く曖昧な状態になっているのをどうにかしたいと言っている
現在 <div />
を含むHTMLをSvelteコンポーネントにコピーペーストしたり、その逆をしたりすると、まったく異なる要素ツリーになってしまう
そうした状況は非常に稀なことなので助けられているが、挙動が異なっている事実は何も変わっていない
<div />こんにちは
上記のようなコードの解釈は人によって異なるので、<div>こんにちは</div>
か<div></div>こんにちは
になるかをSvelteにおいて決めたい
ref: https://github.com/sveltejs/svelte/issues/11052#issuecomment-2035279039
Richが真に問題として上げていることは、人々が不完全なHTMLをSvelteに貼り付けて異なる動作を経験することよりも、逆のことを上げている。
つまり、有効なSvelteのスニペットをHTMLのコンテキストに持っていき、そこで壊れる経験をする人々のことを懸念している
Svelteを使ってHTMLの動作方法を理解した人々が、他のフレームワーク(またはフレームワークを全く使用しない)を使用しようとすると、解釈が異なって壊れることも意味する
今のままのSvelteを提供することは人々に壊れたコードを書いていくことにつながるので、非常に悪いことだと考えている
ref: https://github.com/sveltejs/svelte/issues/11052#issuecomment-2035357540
いくつかコミュニティ内から質問が出た中でRichが明らかにしたいこととして、今回の件はHTML 要素にのみ適用されることを指している。他の名前空間(SVGなど)では、Self-closing tagは許可されている。その延長として、Svelte コンポーネント自体もSelf-closing tag持ち続ける、と述べている
ref: https://github.com/sveltejs/svelte/issues/11052#issuecomment-2035519344
Richが警告が出るように修正PRを出していた。npx svelte-migrate self-closing-tags
でマイグレーションできそう。