111 lines
4.7 KiB
Markdown
111 lines
4.7 KiB
Markdown
## yesod-bin: the Yesod executable
|
|
|
|
This executable is almost exclusively used for its `yesod devel`
|
|
capabilities, providing a development server for web apps. It also
|
|
provides some legacy functionality, almost all of which has been
|
|
superceded by functionality in the
|
|
[Haskell Stack build tool](http://haskellstack.org/). This README will
|
|
speak exclusively about `yesod devel`.
|
|
|
|
__CAVEAT__ There may be some issues using `yesod devel` in Docker-enabled
|
|
projects. See [comment on
|
|
Github](https://github.com/yesodweb/yesod/pull/1305#issuecomment-263204471).
|
|
|
|
### Development server
|
|
|
|
The development server will automatically recompile your application
|
|
whenever you make source code changes. It will then launch your app,
|
|
and reverse-proxy to it. The reverse proxying ensures that you can
|
|
connect to your application on a dedicated port, always get the latest
|
|
version available, and won't get dropped connections when the app
|
|
isn't yet ready. Instead, you'll get some very motivating messages:
|
|
|
|

|
|
|
|
## Common workflows
|
|
|
|
The standard Yesod scaffoldings are configured to work with `yesod
|
|
devel` out of the box (though see below for non-Yesod
|
|
development). For the most part, from within your application
|
|
directory, you'll just want to run:
|
|
|
|
* `stack build yesod-bin`
|
|
* `stack exec -- yesod devel`
|
|
|
|
This will install the corresponding version of the `yesod` executable
|
|
into your currently selected snapshot, and then use that
|
|
executable. (Starting with version 1.5.0, you can be more lax and use
|
|
a `yesod` executable compiled for a different snapshot. Once 1.5.0 is
|
|
more widespread we'll probably update these instructions.)
|
|
|
|
Some other common questions:
|
|
|
|
* If you want to control which port you can access your application
|
|
on, use the `--port` command line option, e.g. `stack exec -- yesod
|
|
devel --port 4000`. Changing your port inside your source code _will
|
|
not work_, because you need to change the reverse proxying port.
|
|
* If you want to run a command after each successful build, you can
|
|
use `stack exec -- yesod devel --success-hook "echo Yay!"`
|
|
* If for some reason you want to disable the reverse proxy
|
|
capabilities, use `stack exec -- yesod devel
|
|
--disable-reverse-proxy`
|
|
|
|
## How it works
|
|
|
|
The workflow of the devel server is pretty simple:
|
|
|
|
* Launch a reverse proxy server
|
|
* Use Stack file-watch capability to run a build loop on your code,
|
|
rebuilding each time a file is modified
|
|
* Have Stack call `yesod devel-signal` to write to a specific file
|
|
(`yesod-devel/rebuild`) each time a rebuild is successful
|
|
* Each time `yesod-devel/rebuild` is modified:
|
|
* Kill the current child process
|
|
* Get a new random port
|
|
* Tell the reverse proxy server about the new port to forward to
|
|
* Run the application's devel script with two environment variables
|
|
set:
|
|
* `PORT` gives the newly generated random port. The application
|
|
needs to listen on that port.
|
|
* `DISPLAY_PORT` gives the port that the reverse proxy is
|
|
listening on, used for display purposes or generating URLs.
|
|
|
|
Now some weird notes:
|
|
|
|
* The devel script can be one of the following three files. `yesod
|
|
devel` will search for them in the given order. That script must
|
|
provide a `main` function.
|
|
* `app/devel.hs`
|
|
* `devel.hs`
|
|
* `src/devel.hs`
|
|
* Unfortunately, directly killing the `ghc` interpreter has never
|
|
worked reliably, so we have an extra hack: when killing the process,
|
|
`yesod devel` also writes to a file
|
|
`yesod-devel/devel-terminate`. Your devel script should respect this
|
|
file and shutdown whenever it exists.
|
|
* If your .cabal file defines them, `yesod devel` will tell Stack to
|
|
build with the flags `dev` and `library-only`. You can use this to
|
|
speed up compile times (biggest win: skip building executables, thus
|
|
the name `library-only`).
|
|
|
|
If that all seems a little complicated, remember that the Yesod
|
|
scaffolding handles all of this for you. But if you want to implement
|
|
it yourself...
|
|
|
|
## Non-Yesod development
|
|
|
|
If you'd like to use the `yesod devel` server for your non-Yesod
|
|
application, or even for a Yesod application not based on the
|
|
scaffolding, this section is for you! We've got a
|
|
[sample application in the repository](https://github.com/yesodweb/yesod/tree/master/yesod-bin/devel-example)
|
|
that demonstrates how to get this set up. It demonstrates a good way
|
|
to jump through the hoops implied above.
|
|
|
|
One important note: I highly recommend putting _all_ of the logic in
|
|
your library, and then providing a `develMain :: IO ()` function which
|
|
yoru `app/devel.hs` script reexports as `main`. I've found this to
|
|
greatly simplify things overall, since you can ensure all of your
|
|
dependencies are specified correctly in your `.cabal` file. Also, I
|
|
recommend using `PackageImports` in that file, as the example app
|
|
shows.
|