ViteでSSIっぽいインクルードをするプラグインを作った
Viteを使用した開発で、HTMLをインクルードするだけの薄いプラグインが欲しかったので作った話です。
作ったViteプラグイン
Vite Plugin Ssincというプラグインになります。SSI(Server Side Includes)の#include
っぽい挙動をViteでサポートするものになります。
ざっくりできること
詳しい使い方はREADME.mdにもありますが、ざっくり以下のような挙動をサポートしたものになります。
ビルド前: header
とfooter
を別ファイルとして切り出してインクルードする。
<header>This is header</header>
<footer>This is footer</footer>
<!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>
ビルド後: header
とfooter
が挿入された状態で吐き出される。
<!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では以下の部分にあたります。
<!--# include file="" -->
の部分を正規表現で指定し、一致した文字列からファイルまでのパスを取得しています。その後、取得したパスを元にNode.jsのreadFile()
ファイルの中身を読み込み、コメントアウトの部分を置き換えています。
他には簡単なキャッシュを持たせたり、拡張子をオプションとして指定する記述もあるのですが、大まかな仕組みとしては以上になります。非常に単純ですね。
おわりに
Viteプラグインを作ってみたという話でした。ViteプラグインにはプラグインAPIとして誰でも簡単に作れるような環境が用意されているので、既存の状態で足りないものがあれば、ぜひ自作プラグインを作ってみてください!
Discussion