[不具合注意報] VScodeのLiveServerでHTMLが正常に読み込まれない不具合を発見!

2024年3月19日

プログラミング

eyecatch 先日ブログで書いた、VScode(VisualStudioCode)のLiveServer機能拡張の、バグとも思われる不具合を見つけたので、共有します。

不具合内容

<svg></svg> <svg></svg> たったこれだけのコードを、VScodeのLiveServerで表示してみましょう。 ※わかりやすくブラウザのソースを表示するモードで見てみると、次のようになっています。 <svg><!-- Code injected by live-server --> <script> // <![CDATA[ <-- For SVG support if ('WebSocket' in window) { (function () { function refreshCSS() { var sheets = [].slice.call(document.getElementsByTagName("link")); var head = document.getElementsByTagName("head")[0]; for (var i = 0; i < sheets.length; ++i) { var elem = sheets[i]; var parent = elem.parentElement || head; parent.removeChild(elem); var rel = elem.rel; if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") { var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, ''); elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf()); } parent.appendChild(elem); } } var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://'; var address = protocol + window.location.host + window.location.pathname + '/ws'; var socket = new WebSocket(address); socket.onmessage = function (msg) { if (msg.data == 'reload') window.location.reload(); else if (msg.data == 'refreshcss') refreshCSS(); }; if (sessionStorage && !sessionStorage.getItem('IsThisFirstTime_Log_From_LiveServer')) { console.log('Live reload enabled.'); sessionStorage.setItem('IsThisFirstTime_Log_From_LiveServer', true); } })(); } else { console.error('Upgrade your browser. This Browser is NOT supported WebSocket for Live-Reloading.'); } // ]]> </script> </svg> <svg><!-- Co scriptタグがsvgタグに勝手に挿入されるのは、前回の報告してあるとおりですが、1ページ内に2つsvgタグが発生していると、上記のように2つめの途中(開始直後)に、文字列が途切れてしまっています。 これは、svgタグだけじゃなくても、文字列が多い場合や、imgタグなどでも同じ症状が確認できました。 でも、文字数などの制限があるわけではなく、詳細な数値特定までは出来ませんでした。

この障害が起こり得るケース

サンプルで表示しているHTMLは、HTMLタグも無ければ、HEADタグもBODYタグも、DOCTYPEタグも書かれていません。 でも、HTMLを部分的なモジュールパーツとして、ajaxで読み込もうとする時、こうしたHTMLパターンで読み込むケースが、個人的には多々あります。 別に本番では、LiveServerを使うわけではないので、開発時だけの話なのだが、デバッグ確認などがまるでできないことになる。 LiveServerの設定でなんとかなるかと思っていじってみたが、まるで駄目。 は小パターンも、コツがまだ掴めていないので、なんとなくランダムでいきなり画面がバグる感じである。

簡易な解決方法

いろいろと、調査をしていて、この事象を手軽に解決する方法をいくつか見つけたので、シェアしておく。

1. LiveServerではなく、Dockerを使ってデバッグ

もはや、便利すぎるけど、この致命的なバグを回避するための、コレといった施策が無いので、Dockerでのローカルサーバー立ち上げで対応する。 Dockerじゃなくても、サーバーエミュレートでもいいし、ローカルapacheやMAMPなどでもいいだろう。

2. htmlとbodyタグをちゃんと書く

htmlファイルを正常に読み込みたいのであれば、ちゃんとHTMLの構文通りの書式を読み込むべし! ということで、お作法通りのHTML書式にすると、正常に読み込むことができた。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <svg></svg> <svg></svg> </body> </html> 結果は次の通り <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <svg></svg> <svg></svg> <!-- Code injected by live-server --> <script> // <![CDATA[ <-- For SVG support if ('WebSocket' in window) { (function () { function refreshCSS() { var sheets = [].slice.call(document.getElementsByTagName("link")); var head = document.getElementsByTagName("head")[0]; for (var i = 0; i < sheets.length; ++i) { var elem = sheets[i]; var parent = elem.parentElement || head; parent.removeChild(elem); var rel = elem.rel; if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") { var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, ''); elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf()); } parent.appendChild(elem); } } var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://'; var address = protocol + window.location.host + window.location.pathname + '/ws'; var socket = new WebSocket(address); socket.onmessage = function (msg) { if (msg.data == 'reload') window.location.reload(); else if (msg.data == 'refreshcss') refreshCSS(); }; if (sessionStorage && !sessionStorage.getItem('IsThisFirstTime_Log_From_LiveServer')) { console.log('Live reload enabled.'); sessionStorage.setItem('IsThisFirstTime_Log_From_LiveServer', true); } })(); } else { console.error('Upgrade your browser. This Browser is NOT supported WebSocket for Live-Reloading.'); } // ]]> </script> </body> </html> でも、部分HTMLのモジュールなので、これではダメなんだよな〜。

3. BODYの閉じタグだけを書く

htmlに実際、html,bodyタグを書いてみたところ、表示不具合が起きなかったので、いろいろとさぐっていたところ、 bodyタグの閉じタグだけを、最終行に書くと、正常に最後まで表示される事がわかった。 <svg></svg> <svg></svg> </body> こうすることで、次のようなソースが出力された。 <svg></svg> <svg></svg> <!-- Code injected by live-server --> <script> // <![CDATA[ <-- For SVG support if ('WebSocket' in window) { (function () { function refreshCSS() { var sheets = [].slice.call(document.getElementsByTagName("link")); var head = document.getElementsByTagName("head")[0]; for (var i = 0; i < sheets.length; ++i) { var elem = sheets[i]; var parent = elem.parentElement || head; parent.removeChild(elem); var rel = elem.rel; if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") { var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, ''); elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf()); } parent.appendChild(elem); } } var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://'; var address = protocol + window.location.host + window.location.pathname + '/ws'; var socket = new WebSocket(address); socket.onmessage = function (msg) { if (msg.data == 'reload') window.location.reload(); else if (msg.data == 'refreshcss') refreshCSS(); }; if (sessionStorage && !sessionStorage.getItem('IsThisFirstTime_Log_From_LiveServer')) { console.log('Live reload enabled.'); sessionStorage.setItem('IsThisFirstTime_Log_From_LiveServer', true); } })(); } else { console.error('Upgrade your browser. This Browser is NOT supported WebSocket for Live-Reloading.'); } // ]]> </script> </body> divやhtmlなどでは駄目で、bodyの閉じタグしか有効にならなかった。 これを見てわかるのは、どうやら、LiveServerは、/bodyタグを探して、scriptタグを埋め込むという動きをするために、それが無かった場合に誤作動を起こしているんだと思う。 前回書いたsvgにscriptタグが埋め込まれていたんじゃなく、/bodyタグが無かったからのようだ。 ※でも、その症状、svgタグだけなんだよな〜

4.. html拡張子じゃなく、.txt拡張子でやる

試しに、htmlの読み込み拡張子を、.txtに変更してみたら、何の問題もなく読み込まれることがわかった。 <svg></svg> <svg></svg> しかも、読み込み後も、変なスクリプトが埋め込まれることも無くだ! もしかしたら、この方法が一番いいのかもしれない。 html以外の拡張子であれば、内部テキスト扱いになって、結構スムーズにいけそうだ。 ちなみに、php拡張子でもうまく読めたが、php実行ファイルと勘違いされないかという問題もあるので、txtが無難そうである。

あとがき

今回こだわってデバッグしまくったのは、このHTMLのモジュールパーツ読み込みは、自分が個人的によくつかう手法で、仕事でもバリバリにこの方式でホームページ制作などをやりまくっているからである。 もちろん、本番サイトでは何の問題もないし、SEOで蹴られることもいまのところほぼ無い。 だけど、便利ツールのLiveServerだけで不具合が出てしまったので、今回解消しておきたくなったという次第である。 世の中なんとも世知辛いよね。 完璧だと思っていたやり方なのに、ちょっとしたほころびがあったなんて・・・ でも、転んでもただでは起き上がらないぞ!と。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ