Reputation: 324
What tools or strategies are people using to hot reload a server built with Servant in Haskell? I am looking for an experience similar to JS land (nodemon, vite).
My current approach is convoluted and slow.
I have a command that starts a js websocket server and then uses watchexec
to run both my haskell server and a refresh script. The refresh script waits for the haskell server to be ready and then sends a message through the js websocket server. The client html has a small script that listens for the refresh messages.
A lot of moving parts, but it works. The main issue is the speed. I am using cabal repl
with a .ghci
file to run the server and execute the main function on .hs
file saves. With my tiny project, it can take ~5s for the repl to restart, modules to load, server to restart, and the reload script to message the browser and refresh.
One improvement would be to not restart the whole repl, just stop the server, reload modules, and restart the server. It's not obvious to me if this is possible - essentially signalling the repl to stop its current command and then execute new ones. I tried using ghcid
as well, but it doesn't seem to be able to reload the repl while the server is running.
Once the repl isn't being killed and restarted it would also seem possible to only reload changed modules which would be a much bigger win.
Open to any suggestions, thanks!
Edit:
Thinking about the approach of using hint and fswatch
hint docs mention that you cannot load a module from the current package. Does that mean I should have a separate package - call it server-dev - that runs the package my server is in?
Once I have a process that can watch modules and load them, is it feasible to do that and run the server in one haskell process, possibly with async? If it is doable in one process, would I need to stop and start the server or would it get the reloaded modules automatically?
Edit Edit:
After much hacking of custom solutions, I've been led to the promised land of ghcid. The command I need is ghcid --command="cabal repl my-server" --test=":main"
, where main
runs my servant server. This works very well for my small server. The -W
flag is also good to add to allow running the "test" command even if there are warnings.
I am still looking for a seamless way to notify the client for auto-refresh. If I find a user-friendly way to do so, I will report back!
Upvotes: 2
Views: 224