PureScriptをViteでホットリローディング(purescript-jellyサンプルあり)
PureScript で purescript-jelly のような UI ライブラリを使い、Vite で Hot Module Replacement しながら開発する手順とサンプル構成の紹介。
概要
PureScript で purescript-jelly みたいな UI ライブラリを使おうとする。 で、そういうときにサーバーを立てて、hot reloading——まあ、正確には Hot Module Replacement ——しながら開発する例って、あまり見当たらない。
それで、謝辞にも書いた @himanoa さんや @amderbar さんの記事を見つけた。基本的なアイディアはそこからもらいつつ、自分でも Hot Module Replacement のサンプルを作ってみた。
この記事では、それを紹介する。
謝辞
以下の記事を参考にした。
ディレクトリ構成
以下のような形のディレクトリ構成になる。
public/index.html がブラウザに表示する、HTML だ。
public/index.html から、public/index.jsを読み込むようにする。
public/index.js は、PureScript ファイルsrc/Main.purs をトランスパイルしたものだ。
.
├── output
│ ├── cache-db.json
│ ├── 以下略
│
│
├── package.json
├── package-lock.json
├── packages.dhall
├── public
│ ├── index.html
│ ├── index.js
│ └── vite.svg
├── spago.dhall
├── src
│ └── Main.purs
├── test
│ └── Main.purs
└── vite.config.js
バージョン情報
Node.js v23.8.0
手順
以下の二段階がある。
- npm パッケージのインストール。
- PureScript のパッケージマネージャー spago でのインストール
npm パッケージのインストール
npm init
今日、2025 年 2 月現在は、spago@nextをインストールするとのこと。
npm install --save-exact esbuild purescript spago@next
npm install --save-exact --save-dev vite chokidar
sudo pacman -S watchexec
spago パッケージのインストール
PureScript Jelly をつかうため、以下をインストール。
npx spago init
npx spago run
npx spago install jelly
npx spago install aff
npx spago install jelly-signal
npx spago install foldable-traversable
package.json の設定
"scripts": {
"dev:vite": "vite",
"watch:spago": "spago bundle-app --watch --to ./public/index.js",
"dev": "npm run dev:vite & npm run watch:spago",
"build:spago": "spago bundle-app --to ./public/index.js",
"preview": "vite preview"
},
"watch:spago": "spago bundle-app --watch --to ./public/index.js"
これで、spago 側で、PureScript のファイルを watch し、変更があれば、
./public/index.jsにバンドルする。
そして、その変化を検知した、vite が画面をリロードする。 という流れにしたい。 そのために、vite と同時に、spago の監視を以下のように実行する。
"dev": "npm run dev:vite & npm run watch:spago",
vite.config.mjs の 設定
import { defineConfig } from "vite";
export default defineConfig({
root: "./public",
server: {
watch: {
ignored: ["!./public/index.js"],
},
},
});
ディレクトリ構成で述べたように、public/index.html をブラウザに表示する、HTML にしたい。
したがって、root: "./public",を設定。
また、PureScript のバンドル結果の./public/index.jsを vite の watch 対象にする。
public/index.html の設定
./index.jsを読み込むようにする。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./index.js"></script>
</body>
</html>
src/Main.purs の設定
これは、公式にあるものをそのままコピペする。
jelly.yukikurage.net/docs/hello-world
module Main where
import Prelude
import Data.Foldable (traverse_)
import Effect (Effect)
import Effect.Aff (launchAff_)
import Effect.Class (liftEffect)
import Jelly.Aff (awaitBody)
import Jelly.Component (Component, text)
import Jelly.Hooks (runHooks_)
import Jelly.Hydrate (mount)
main :: Effect Unit
main = launchAff_ do
appMaybe <- awaitBody
liftEffect $ runHooks_ $ traverse_ (mount component) appMaybe
component :: forall m. Component m
component = text "Hello World!"
動作確認
npm run dev を実行してみる。