BLOG
ViteとEleventyで静的サイト構築
INDEX
先日発表されたThe State of JavaScript 2021では98%の満足度を獲得しエンジニアからの高い注目度がうかがえるViteですが、ビルドツールのため静的なページの生成には別途仕組みが必要になるかと思います。
公式のテンプレートにはVueやReactなどがサポートされていますが、これらは学習コストやプロジェクトの要件にもより気軽に導入できるものではないかもしれません。
そこで今回はページの生成に静的サイトジェネレーターのEleventy(以下、11ty)を利用し、Viteの高速な開発体験の恩恵を受けつつ11tyでページを生成するシンプルな静的サイトの開発環境を作ってみたいと思います。
※11tyについての記事はこちら (バージョンが記事公開時より更新されていますので利用の際は公式ドキュメントをご確認ください)
環境
- Node.js: v16.12.0 ※Viteの利用には12.2.0以上のバージョンが必要です。
- @11ty/eleventy: ^1.0.0
- vite: ^2.8.6
- ディレクトリ構成
├── .eleventy.js
├── _site: 出力
│ ├── index.html
│ └── main.js
├── package-lock.json
├── package.json
├── src: 入力
│ ├── _data
│ │ └── build.js
│ ├── client
│ │ └── main.js
│ └── index.njk
└── vite.config.js
インストール~開発コマンド作成
11tyのインストール
プロジェクトディレクトリに移動したら package.json
を作成し11tyをインストールします。
npm init -y
npm install --save-dev @11ty/eleventy
テンプレートには弊社でもよく利用しているNunjucksを利用します。 /src/index.njk
を作成します。
/src/index.njk
<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<p>hello from 11ty</p>
</body>
</html>
次に11tyの設定ファイルを作成します。プロジェクトルートに .eleventy.js
を作成し下記のように設定します。
/.eleventy.js
module.exports = function (eleventyConfig) {
return {
templateFormats: ['njk', 'html'],
htmlTemplateEngine: 'njk',
dir: {
input: 'src',
output: '_site'
}
}
}
ここまで作成したら11tyを実行します。
npx @11ty/eleventy
これで src
ディレクトリのテンプレートが _site
ディレクトリにコンパイルされます。
ローカルWebサーバーを起動し、生成されたファイルを確認してみます。
npx @11ty/eleventy --serve
11tyのホットリロードローカルWebサーバーが起動しソースファイルに変更を加えるとブラウザが自動でリロードされるのが確認できます。(portは :8080
)
Viteのインストール
次にViteをインストールしていきます。
npm install --save-dev vite@latest
/src/client/main.js
←このようにディレクトリとjsファイルを作成し、テスト用のコードを書いておきます。
/src/client/main.js
function init() {
const successNode = document.createElement('p')
document.body.appendChild(successNode)
successNode.innerText = 'hello from vite'
}
init()
index.njk
に作成したjsを読み込む記述を追加します。
/src/index.njk
...
<p>hello from 11ty</p>
<script type="module" src="http://localhost:3000/src/client/main.js"></script>
</body>
11tyとViteを並列に実行
開発の際は11tyとViteを並列に起動し11tyのローカルサーバーでファイルを確認します。コマンドは npx @11ty/eleventy --serve & npx vite
のようにつなげても動作しますが、記述が煩雑になりやすいのとOS環境への依存を避けるためツールを利用します。concurrentlyという複数のコマンドをまとめて実行できるパッケージがありますのでこちらをプロジェクトに追加します。
npm install --save-dev concurrently
package.json
の scripts
に開発コマンドをまとめます。
/package.json
...
"scripts": {
"dev": "concurrently npm:dev:*",
"dev:eleventy": "eleventy --serve",
"dev:vite": "vite"
},
これで下記コマンドを実行し localhost:8080
(11tyの方。Viteはデフォルトで localhost:3000
)で開発を行います。
npm run dev
プロダクションビルド
ビルドタスクの作成
開発時の設定はできたので、最後にビルドタスクを作成します。プロジェクトルートに vite.config.js
を作成しオプションを下記のように設定します。
/vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
build: {
outDir: '_site',
rollupOptions: {
input: '/src/client/main.js',
output: {
entryFileNames: 'main.js',
}
}
}
})
Viteはビルド時のバンドルにrollup.jsを採用しており rollupOptions
を変更することでファイル名など出力時の設定がカスタムできます。詳しくはこちら。
また、 package.json
にビルド用の scripts
を追記し
/package.json
...
"scripts": {
"dev": "concurrently npm:dev:*",
"dev:eleventy": "eleventy --serve",
"dev:vite": "vite",
"build": "npm run build:vite && npm run build:eleventy",
"build:eleventy": " eleventy",
"build:vite": "vite build"
},
下記コマンドでビルドします。
npm run build
これで _site
ディレクトリにビルドされた main.js
が出力されます。
開発時とビルド時でコードを分岐
現状のコードではjsをソースファイルから直接読み込んでいますが(開発時にViteが高速なのはこのためです)、サイトのデプロイ時にはバンドルされたアセットを読み込む必要があります。そのため開発時とビルド時で環境変数を利用しコードを分岐させます。
/src/_data/build.js
←このようにディレクトリとjsファイルを作成し、環境変数を格納しておきます。
/src/_data/build.js
module.exports = {
env: process.env.NODE_ENV
}
次に index.njk
のjs読み込み箇所をif文(Nunjucksテンプレートタグ)で分岐します。
/src/index.njk
...
<p>hello from 11ty</p>
{% if build.env === "production" %}
<script type="module" src="./main.js"></script>
{% else %}
<script type="module" src="http://localhost:3000/src/client/main.js"></script>
{% endif %}
</body>
package.json
のビルドコマンドに環境変数を追記します。
/package.json
...
"scripts": {
"dev": "concurrently npm:dev:*",
"dev:eleventy": "eleventy --serve",
"dev:vite": "vite",
"build": "npm run build:vite && npm run build:eleventy",
"build:eleventy": "NODE_ENV=production eleventy",
"build:vite": "NODE_ENV=production vite build"
},
これで再度 npm run build
を行うと、jsの読み込み箇所がプロダクション用に書き換わっているのが確認できるかと思います。
終わりに
この記事では取り扱っていませんが、ViteはSassもパッケージを追加してscssをjsにインポートするだけで利用できます。公式にも記載がありますのでこちらを参考にしてみてください。