BrowserSync が勝手にパスを変えてきやがるので矯正する

BrowserSync を使って開発しているのだが、何故かリンクのパスを勝手に書き換えてきやがって「Can't GET」エラーが発生してしまう。

本来、次のような URL に遷移するリンクなのだが、

なぜだか次のようなパスに変換されてしまう。

リンクは当然、

<a href="./about/search.html">リンク</a>

このように書いているので、間違われるはずがない。しかし現状、どうしてもこのように間違ったパスに変換されてしまうのだ。

頭に来たので調べたところ、Express と同様のミドルウェアを自分で定義できるらしいので、次のようなミドルウェアを書いて、強制的に対象のファイルが表示できるように直してやった。

const browserSync = require('browser-sync').create();

// ファイルの存在チェックを行う関数
function isExist(targetPath) {
  try {
    fs.statSync(targetPath);
    return true;
  }
  catch(_error) {
    return false;
  }
}

browserSync.init({
  middleware: [
    // 勝手に `/path/to/file.html` へのリンクを `/path/to/file/` でアクセスしようとしてエラーになりやがるので置換する
    // `req.url` はスラッシュ始まり・スラッシュで終わる
    (req, _res, next) => {
      if(isExist(`./public${req.url}index.html`)) {
        // `/path/to/file/` に変換された時、`/path/to/file/index.html` が存在するならその内容を返す
        req.url = `${req.url}index.html`;
      }
      else if(isExist(`./public${req.url.replace((/\/$/u), '.html')}`)) {
        // `/path/to/file/index.html` が存在せず `/path/to/file.html` が存在するならそのファイルへのパスを返す
        req.url = `${req.url.replace((/\/$/u), '.html')}`;
      }
      next();
    }
  // ……
});

このように、req.url を書き換えるという方法で、遷移先 URL と参照する HTML ファイルを調整してやるのだ。

ブラウザのアドレスバーの表示は /path/to/file/ のまま変わらないが、とりあえずやりたいように出来たし、不具合はなさそう。


あと、コレまで serve という npm パッケージで静的な確認をしていたが、この serve も、同様に /path/to/file.html へのリンクを /path/to/file/index.html と解釈したがる癖があって頭に来たので、捨ててやった。

今は代わりに sirv-cli を使っている。コチラはそのようなバカなパス変換をしないので良い子。