🤖

【暫定対応!】astro buildで出力されたHTML内の絶対パスを相対パスに変換する

2023/01/27に公開

Astroにて、buildするとdist配下にindex.htmlが出力されます。
このindex.htmlファイル内のaタグやimgタグ内のhrefやsrc属性には、以下のように絶対パスでリソースの位置が記述されます。

<img alt="" class=astro-TQ5BEMXN decoding=async height=20 src=/original.webp width=20>
<a class="astro-O4MUQTET link" href=/original.pdf rel="noopener noreferrer" target=_blank>DownLoad</a>
<a class=astro-3FF6SSR2 href=/ja/ >日本語</a>

この絶対パスで記述されている部分を相対パスにしたいです。

<img alt="" class=astro-TQ5BEMXN decoding=async height=20 src=./original.webp width=20>
<a class="astro-O4MUQTET link" href=./original.pdf rel="noopener noreferrer" target=_blank>DownLoad</a>
<a class=astro-3FF6SSR2 href=./ja/index.html >日本語</a>

しかしながら、現状Astro公式ではサポートされていないようです。
※ただし、提案はされているので、将来的には簡単に設定できるかもしれません。
https://github.com/withastro/roadmap/pull/381

(2023/3/27追記)
こちらのIntegrationを追加すれば行けるかもしれません!(まだ試してないです)
https://github.com/ixkaito/astro-relative-links#readme

また、調べている最中にviteの設定でなんとかなる旨も散見されますが、できませんでした。。(よくわかりませんでした)

そこで、愚直にHTMLファイル内を書き換えるスクリプトを作成しました。

/replaceHtml.mjs
import { writeFileSync, readFileSync } from 'fs';
import glob from 'glob';

const replaceInHtmlFiles = () => {
  try {
    const files = glob.sync('dist/**/*.html');
    for (const file of files) {
      // htmlファイルの読み込み
      const data = readFileSync(file, 'utf8');
      // htmlの置かれているパスから相対(., ..)を算出
      const relativePath = file.replace(/[^/]/g, '').replace(/\//g, '.');
      // href, srcに指定されている絶対パスを置換
      const result = data
        .replace(/href=\//g, `href=${relativePath}/`)
        .replace(/src=\//g, `src=${relativePath}/`)
        .replace(/(<a.*?href.*?\/)(?=\s>)/g, '$1index.html');
      writeFileSync(file, result, 'utf8');
    }
  } catch (error) {
    console.log(error);
  }
};

replaceInHtmlFiles();

要件としては、以下になります。

  • href属性の/から始まる絶対パスを相対パスにする
  • src属性の/から始まる絶対パスを相対パスにする
  • ページ遷移を伴う箇所(aタグかつ"/"で終わる)は、相対パスにした上でindex.htmlを付与する
  • 対象のhtmlは、/dist/index.html, /dist/ja/index.htmlのように存在し、/dist/には、画像ファイル、/dist/_astro/にはcssが存在します。

これらを実現したのが上記のmjsファイルになります。
そして、ターミナルで以下のコマンドを叩けば完成です。

node replaceHtml.mjs

そこまでAstro関係ないのと、リファクタしていないので汚いコードですが、取り急ぎパッと変換したい方に役立てば幸いです。

そして、もう少しまともな方法あれば、是非教えて下さい(切実)

Discussion