先日ブログで書いた、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だけで不具合が出てしまったので、今回解消しておきたくなったという次第である。
世の中なんとも世知辛いよね。
完璧だと思っていたやり方なのに、ちょっとしたほころびがあったなんて・・・
でも、転んでもただでは起き上がらないぞ!と。
0 件のコメント:
コメントを投稿