プログラミング初心者にオススメ

Vike(旧vite-plugin-ssr) + ReactでSSGしてみる

「Vike」って知ってますか?
Viteで開発するアプリケーションをもう一段階強化できるものでViteを使用してSSRやSSGなど好きなレンダリングをすることができるようになります。

元々はViteで使用するプラグイン vite-plugin-ssr というものだったらしいのですが名称変更をしたみたいです。

Vite × ReactでSSGを使いたいなと思って探してたところ見つけたのですが動的ルートに対してのSSGに少しだけハマったのでこちらに記しておこうと思います。

今回はVikeを使用してSSGをする方法を書くのでVikeの紹介や詳しい使い方などは割愛します。

公式ドキュメント
Vike

SSGさせるために設定を変更する

まずSSGさせるためにはVikeの設定をSSG用に変える必要があります。

vite.config.jsのvikeプラグインの引数をprerender: trueに設定。

// vite.config.js
 
import vike from 'vike/plugin'
 
export default {
  plugins: [
    vike({ prerender: true })
  ]
}

これでビルドするとpages配下に対応したhtmlファイルが生成されます。

ただこれだけだと /category/@id のような動的ルートに対してのhtmlファイルは作成されません。

参考
https://vike.dev/pre-rendering#how-to-pre-render

動的ルートをSSGさせる

動的ルートをSSGするにはビルドプロセスの中でvike側に動的ページのパスのリストを渡してあげる必要があります。

onBeforePrerenderStart() というフックが用意されているのでこれを使います。
名前的にはプリレンダリングつまりhtmlを生成する処理の前に差し込む処理のことだと思います。

// /pages/movie/+route.js
// Environment: Node.js
 
export default '/movie/@movieId'
// /pages/movie/+onBeforePrerenderStart.js
// Environment: Node.js
 
export { onBeforePrerenderStart }
 
async function onBeforePrerenderStart() {
  const movies = await Movie.findAll()
  const moviePageURLs = movies.map(movie => '/movie/' + movie.id)
  return moviePageURLs
}

ドキュメントのコードをそのまま持ってきました。
パスを配列に詰めてreturnしてるだけですね。

実際のコードに当てはめてみた

今回作成していたサイトには /category/@slug という動的ルートがありましたのでドキュメントの通りに以下のようにファイルを作成しました。

// /pages/category/+route.js
 
export default '/category/@slug'
// /pages/category/+onBeforePrerenderStart.js
 
export { onBeforePrerenderStart }

import { categories } from '../../../constants';
 
async function onBeforePrerenderStart() {
  const categoryPageURLs = categories.map(category => `/category/${category.slug}`)
  return categoryPageURLs
}

エラーが発生する

ここで少しハマりました。
ドキュメントの通りにファイルを作成したのですが以下のようなエラーが出ました。

Error: [vike][Wrong Usage] URL /category/work provided twice by the onBeforePrerenderStart() hook (/pages/category/+onBeforePrerenderStart.ts). Make sure to provide the URL only once instead.

同じURLが複数出てるから1回だけにしろ的な感じですかね?
うーん、ちょっとよく分からん。

ってことでvikeの公式リポジトリの中に例がいくつかあるので解決策のヒントがないか探しに行きました。

ここです↓

https://github.com/vikejs/vike/tree/main/examples

解決方法

+route.js
+onBeforePrerenderStart.js

この2つのファイルの配置場所を変えることで解決しました。

/category/+route.js
/category/+onBeforePrerenderStart.js

↓

/category/index/+route.js
/category/index/+onBeforePrerenderStart.js

このようにindexというディレクトリを作ってその中に入れることで解決しました。

https://github.com/vikejs/vike/tree/main/examples/react-full/pages/star-wars/index

解決した理由がよく分からないのですが↑のディレクトリ構造を見て真似してみたら解決した!って感じです。

この辺りが調べても出てこないしissueもなかったのでハマりました、、、

けどこれで動的ルートに関しても無事にSSGさせることができました。

最後に

今回はvike × ReactでSSGさせる方法を書きました。

React要素全然出てこなかったな、、、
SSGさせる方法というよりどっちかっていうとエラー解決記事になってる気がする。

次回はもう少し詳しい説明とか機能とか書きたい。(触り始めたばかりだけど)