wai-devel is a development server for wai compliant haskell web applications.
Its name changed from yesod-devel (the haskell reddit community suggested this). You can find it at: https://github.com/urbanslug/wai-devel
Since wai-devel is very loosely coupled to your application it expects mainly two things from your application: a host:port pair and a function, Application.develMain.
Due to it's dependence on ide-backend it also expects you to set the environment variable
Mine for example is:
The host:port pair is expected to be passed in as two environment variables: wai_host and wai_port for example:
Better yet, the application itself should set the environment variables as in the example code below.
wai-devel looks for a function Application.develMain I have a fork of yesod, that builds a yesod binary which generates a scaffold with this function implemented. I recommend using it to generate the scaffold with which to try out wai-devel with.
The specifics of how to set the port and host within yesod applications will obviously change. The point of this fork is to generate a scaffold that works with wai-devel out of the box.
Here is a snippet develMain function from my yesod fork.
-- | main function for use by yesod devel develMain :: IO () develMain = develMainHelper' getApplicationDev develMainHelper' :: IO (Settings, Application) -> IO () develMainHelper' getSettingsApp = do (settings, app) <- getSettingsApp _ <- unsetEnv "wai_port" >> setEnv "wai_port" "3001" _ <- unsetEnv "wai_host" >> setEnv "wai_host" "127.0.0.1" let settings' = setPort (3001 :: Port) settings settings'' = setHost ((read "127.0.0.1") :: HostPreference) settings\' sock <- createSocket runSettingsSocket settings'' sock app where -- | Create the socket that we will use to communicate with -- localhost:3001 here. createSocket :: IO Socket createSocket = do sock <- socket AF_INET Stream defaultProtocol -- Tell the OS *not* to reserve the socket after your program exits. setSocketOption sock ReuseAddr 1 -- Bind the socket to localhost:3000 and listen. -- I wonder why I can't specify localhost instead of iNADDR_ANY bindSocket sock (SockAddrInet 3001 iNADDR_ANY) listen sock 2 return sock
During socket creation I made sure that the socket option ReuseAddr has been set to 1.
This way the operating system doesn't hold on to the socket after the program exits. This is important for when wai-devel takes note of file changes and the development server is restarted.
wai-devel expects that there will be a single
In the case of having more than one, for example with yesod, we ignore all but one.
Specifically, we ignore the file app/DevelMain.hs.
There is no need for app/devel.hs so it has been removed in my fork.
Moreover, wai-devel ignores files in your
This is because wai-devel depends on ide-backend which will attempt to build all files in the current working diretory, including your test directory. This leads to a world of hurt because the test/ directory also has a
Please report an issue if you would like any file ignored during builds.
Since the Haskell community has moved in this direction, so has wai-devel.
wai-devel only depends on cabal in that stack and ide-backend depend on Cabal the library. Otherwise, the cabal binary is not used and hasn't been tested to work with wai-devel.
Currently wai-devel is built and tested against:
wai-devel watches for file changes on files with the following extensions:
When a change takes place wai-devel will recompile and re-run your application on localhost:3001 or display an error if any on the browser at localhost:3000
If you would want another extension added to the list of file extensions to watch for please report it as an issue.
Currently wai-devel takes only these two arguments and the two are optional. If you feel the need for more arguments please report it as an issue on github.
-r to turn off reverse proxying If this is turned on you will access your application at an address that is specific to your web application or web framework.
--show-iface [hi file] passes this command to ghc Same as ghc --show-iface