I currently use
Yesod along with
Keter for the
seattlehaskell.org web site and I’m very pleased with it. The site has a very small dynamic portion, specifically the bit which queries the
Meetup API to list upcoming meetings on the web site’s front page.
In
order to support future static content, I really want to use a static
content generator and the obvious choice for a Haskell-based and
Haskell-themed web site is
Hakyll.
So, the problem is that I would like the dynamic portions of my web
site to use Yesod, the static portions to use Hakyll and, yet, I would
like to keep the two visually consistent. Over the course of a few blog
posts, I will describe the various steps I have taken to make this
happen. Note, that I haven’t launched the new variant of the site yet
and, so, some of the approaches I will describe are still experimental.
Part 1: Apache configuration
I use
Apache
as the front end web server and, so, the first problem is how to serve
such a “blended” web site. I have Keter serving my Yesod application on
port 3000 and I would like all my static content to be presented under
the virtual subdirectory
content
. So, given a domain name of
mydomain.com
, here are a few examples of the routing that I would like to configure:
- Routed to Keter/Yesod:
http://mydomain.com/
(dynamic portion of Yesod app)
http://mydomain.com/about
(dynamic portion of Yesod app)
http://mydomain.com/static/css/bootstrap.css
(static portion of Yesod app)
- Routed to Apache’s document root:
http://mydomain/content/
http://mydomain/content/about
http://mydomain/content/pages/foo
To achieve this, I use the following Apache configuration:
ServerAlias www.mydomain.com |
ServerAdmin admin@mydomain.com |
ProxyPass / http://0.0.0.0:3000/ |
ProxyPassReverse / http://0.0.0.0:3000/ |
Alias /content /var/www/mydocroot/ |
<Directory /var/www/mydocroot/> |
DirectoryIndex index.html |
# Rewrite rules described here: |
# http://stackoverflow.com/questions/1992183/how-to-hide-the-html-extension-with-apache-mod-rewrite |
# Rewrite URLs without .html extension |
RewriteCond %{REQUEST_FILENAME} !-d |
RewriteCond %{REQUEST_FILENAME}\.html -f |
RewriteRule ^(.*)$ $1.html |
# Redirect URLs with .html extension |
RewriteCond %{THE_REQUEST} ^[A-Z]+\ (/[^\ ]*)\.html[?\ ] |
RewriteRule (.*)\.html$ /content/$1 [R=307,L] |
This sets up reverse proxing to
http://0.0.0.0:3000/
for all URLs whose root directory is
not content
. All URLs under
content
are rooted to the document root. This configuration also does nice URL rewriting so that the
.html
file name extension is not needed for files that exist in the document root. Furthermore, if the request does include
.html
, the server will issue an HTTP 307 redirect to the extensionless URL - thus ensuring one version of truth.
I already have this reverse proxying set up at
seattlehaskell.org with the Keter-hosted
Yesod application up and running. Currently, the static content consists of a single
“Hello World” file. This will eventually be replaced with my Hakyll-generated static content.
from http://blog.rcook.org/blog/2016/yesod-and-hakyll-together-part-1/
-------------
There’s no code today. Just lots and lots of words. Code will follow soon!
Both
Yesod and
Hakyll are well-documented and have reasonable tutorials: both
Michael Snoyman’s book and Jasper Van der Jeugt’s site are great resources.
Template system mismatches
What
is not documented is how to combine the two. Part 1 of this series
describes my Apache configuration for serving content from the two parts
of the web site. After figuring that out, the most difficult challenge
was making the two parts of the sites look and feel as if they were part
of a single coherent site. The single biggest complexity is that both
frameworks employ different templating systems by default. Yesod employs
Shakespearean templates,
specifically Hamlet, Lucius and Cassius. Hakyll has its own
straightforward, but effective, system. I enumerate some of the
interesting characteristics below:
- Shakespearean templates
- Strongly-typed templates that are parsed at compile time
- Dynamic “runtime” variants of the templates are supported,
but are decidedly “second-class” compared to the strongly-typed
variants as one might expect given that Yesod’s strong emphasis on type
safety
- Hamlet (the HTML templates) use a Haml-based syntax
- Hakyll templates
- HTML-based
- Fully dynamic much more like the kinds of templates that non-Haskell developers are typically used to
Philosophical thoughts
Both
systems have their pros and cons. However, on a personal note, I have a
soft spot for Hamlet’s syntax. However, I don’t object to using real
HTML. Ultimately, the question came down to the following: do I adapt my
Yesod app to consume Hakyll templates or do I adapt my Hakyll site
generator to handle the templates from my Yesod app. Given my
unwillingness to compromise the type safety of my Yesod app, I decided
to do the latter.
Possible approaches
There were three main approaches I considered:
- Add
an “empty” page to my Yesod app whose sole purpose is to serve up its
default layout template rendered as HTML containing Hakyll-style
placeholders: in this model, I’d run a local Yesod development instance
while running my Hakyll generator: the Hakyll generator would pull its
default layout template from the Yesod app using the Haskell equivalent
of
wget
and then use that to render the static site
- Add Hamlet support directly to my Hakyll site generator
I
toyed with the first approach briefly and then decided that this was
not personally very satisfying. Both Yesod and Hakyll are highly modular
and configurable frameworks, so I decided to power through things and
simply use the
shakespeare
in my Hakyll app.
As
I’ll describe in future instalments of this series, this was not
entirely straightforward, but did ultimately result in a reasonably
elegant solution to the problem.
from http://blog.rcook.org/blog/2016/yesod-and-hakyll-together-part-2/
No comments:
Post a Comment