Closed11

Svelte parses HTML all wrongについてまとめる

yamanokuyamanoku

そもそもの事と起点としては「Don't self-close void elements, because invalid when using HTML5」というIssue

https://github.com/sveltejs/svelte/issues/8923

SvelteKitがHTML5 doc typeを使用しているため、W3C ValidatorがビルドされたHTMLに対して警告が出る

具体的にはmetalinkといった空要素に終了タグが加わっていることで警告が入っている

yamanokuyamanoku

関連する箇所は以下のコード部分
https://github.com/sveltejs/kit/blob/df6641a701f8155d7023ab6a5b17ef39df31d730/packages/create-svelte/templates/skeleton/src/app.html

Prettierによる整形の影響で閉じタグが付いてしまっているため、RichによってSvelteによる問題ではないことが判明できた

ただこの件によりSvelteが空要素のself-closingに対して誤って解釈されている問題についてを知るきっかけになった

yamanokuyamanoku

Richは下記のようなdiv要素自体に閉じタグを付ける場合

<div />

以下のようなショートハンドになると思っていた

<div></div>

しかしHTML自体には自己完結型タグというものは存在しないため、以下のようなコードは

<div />こんにちは!

閉じタグは無視されて以下のように判定される

<div>こんにちは!</div>

Codepenによるサンプル


このHTMLの振る舞いとSvelteの解析を比較すると、Svelteは誤った解釈をしていたことがわかった

ref: https://github.com/sveltejs/svelte/issues/11052#issue-2223254077

yamanokuyamanoku

本来はSelf-closingな空要素を許可しないことになる(これはHTMLにのみ適用され、他の名前空間には適用されない)
これを許可しないことになるのは大きな変更になるが、代替案を用意する

  1. 現状の間違ったHTMLの解析を続ける
  2. HTMLを正しく解析し、<div /><div></div>として扱う。破壊的な変更だけど、デバッグするのは悪夢のようだ

理想的には、Self-closingな空要素(つまり <input> ではなく <input /> な要素)も禁止したいところだが、これが現実的かどうかは、空要素に不要な /> を追加する Prettier の現在の挙動においてそれを妨げるかどうかによる

ref: https://github.com/sveltejs/svelte/issues/11052#issue-2223254077

yamanokuyamanoku

以下のようなSvelteコンポーネントにおいては

<script>
  import { onMount } from 'svelte';

  let div;
	
  onMount(() => {
    console.log(div.textContent);
  });
</script>

<div bind:this={div} />hello!

1番目のケースは'hello!' がログに記録されて、2番目のケースでは、空の文字列がログに記録されるようになる

yamanokuyamanoku

Svelteの既存の振る舞いを変える可能性があることに賛同しない人もいるが、Rich曰く曖昧な状態になっているのをどうにかしたいと言っている

現在 <div /> を含むHTMLをSvelteコンポーネントにコピーペーストしたり、その逆をしたりすると、まったく異なる要素ツリーになってしまう

そうした状況は非常に稀なことなので助けられているが、挙動が異なっている事実は何も変わっていない

<div />こんにちは

上記のようなコードの解釈は人によって異なるので、<div>こんにちは</div><div></div>こんにちはになるかをSvelteにおいて決めたい

ref: https://github.com/sveltejs/svelte/issues/11052#issuecomment-2035279039

yamanokuyamanoku

Richが真に問題として上げていることは、人々が不完全なHTMLをSvelteに貼り付けて異なる動作を経験することよりも、逆のことを上げている。

つまり、有効なSvelteのスニペットをHTMLのコンテキストに持っていき、そこで壊れる経験をする人々のことを懸念している

Svelteを使ってHTMLの動作方法を理解した人々が、他のフレームワーク(またはフレームワークを全く使用しない)を使用しようとすると、解釈が異なって壊れることも意味する

今のままのSvelteを提供することは人々に壊れたコードを書いていくことにつながるので、非常に悪いことだと考えている

ref: https://github.com/sveltejs/svelte/issues/11052#issuecomment-2035357540

yamanokuyamanoku

いくつかコミュニティ内から質問が出た中でRichが明らかにしたいこととして、今回の件はHTML 要素にのみ適用されることを指している。他の名前空間(SVGなど)では、Self-closing tagは許可されている。その延長として、Svelte コンポーネント自体もSelf-closing tag持ち続ける、と述べている

ref: https://github.com/sveltejs/svelte/issues/11052#issuecomment-2035519344

このスクラップは2024/04/24にクローズされました