ViteでSSIっぽいインクルードをするプラグインを作った

2023/05/22に公開

Viteを使用した開発で、HTMLをインクルードするだけの薄いプラグインが欲しかったので作った話です。

作ったViteプラグイン

Vite Plugin Ssincというプラグインになります。SSI(Server Side Includes)の#includeっぽい挙動をViteでサポートするものになります。

https://www.npmjs.com/package/vite-plugin-ssinc

ざっくりできること

詳しい使い方はREADME.mdにもありますが、ざっくり以下のような挙動をサポートしたものになります。

ビルド前: headerfooterを別ファイルとして切り出してインクルードする。

header.shtml
<header>This is header</header>
footer.shtml
<footer>This is footer</footer>
index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Vite Plugin Ssinc</title>
  </head>
  <body>
    <!--# include file="header.shtml" -->
    <h1>Welcome to Vite Plugin Ssinc</h1>
    <!--# include virtual="/footer.shtml" -->
  </body>
</html>

ビルド後: headerfooterが挿入された状態で吐き出される。

index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Vite Plugin Ssinc</title>
  </head>
  <body>
    <header>This is header</header>
    <h1>Welcome to Vite Plugin Ssinc</h1>
    <footer>This is footer</footer>
  </body>
</html>

Vite Plugin Ssincでやってること

Viteではプラグインを作成するのためのプラグイン APIが提供されており、これはRollupのプラグインインターフェースを拡張したものになります。

Rollupと共通のフックないしVite特有のフックが提供されていますが、当プラグインで処理のメインとなるのはtransformIndexHtmlフックです。

transformIndexHtmlフック

Dedicated hook for transforming HTML entry point files such as index.html.

ドキュメントにあるようにtransformIndexHtmlフックを用いることで、エントリーポイントのHTMLファイルを変換することができます。以下は公式ドキュメントにある例ですが、第一引数に現在のHTML文字列を受け取ります。

基本的な例
const htmlPlugin = () => {
  return {
    name: 'html-transform',
    transformIndexHtml(html) {
      // html: HTML文字列
      return html.replace(
        /<title>(.*?)<\/title>/,
        `<title>Title replaced!</title>`,
      )
    },
  }
}

現在のHTMLの中身が文字列として渡ってくるので、String.prototype.replace()と正規表現で、HTMLファイルの中身を変換することができるというわけです。

Vite Plugin Ssincでは以下の部分にあたります。

https://github.com/yend724/vite-plugin-ssinc/blob/main/src/index.ts#L42-L90

<!--# include file="" -->の部分を正規表現で指定し、一致した文字列からファイルまでのパスを取得しています。その後、取得したパスを元にNode.jsのreadFile()ファイルの中身を読み込み、コメントアウトの部分を置き換えています。

他には簡単なキャッシュを持たせたり、拡張子をオプションとして指定する記述もあるのですが、大まかな仕組みとしては以上になります。非常に単純ですね。

おわりに

Viteプラグインを作ってみたという話でした。ViteプラグインにはプラグインAPIとして誰でも簡単に作れるような環境が用意されているので、既存の状態で足りないものがあれば、ぜひ自作プラグインを作ってみてください!

Discussion