I use scss for my site’s stylesheets. scss is a language very similar to CSS that adds support for variables, nesting, mixins, selector inheritance, and more—while retaining a syntax very similar to CSS itself.
A common practice I’ve noticed with the use of scss is to avoid having one monolithic stylesheet and instead opt to split it out into separate semantic files. For example, post.scss would concern styling for posts, syntax.scss would concern styling for Pygments syntax highlighting, etc. These files are then imported into one stylesheet, e.g., screen.scss, using the
@import directive. It is this stylesheet that gets compiled by the scss compiler into the monolithic CSS.
In Hakyll, rules are generally designated by a pattern that matches a resource coupled with a route and a compiler. So this was the rule I originally had for scss/screen.scss:
match "scss/screen.scss" $ do route $ constRoute "css/screen.css" compile $ sassCompiler
The rule simply states that Hakyll should:
- find the file scss/screen.scss
- route it to css/screen.css
- compile it using my custom
This worked fine, but it meant that when I built or previewed the site, if I modified one of the split stylesheets, such as post.scss, it wouldn’t regenerate the monolithic stylesheet. It would only do so if scss/screen.scss itself was modified.
With the help of Hakyll’s creator, Jasper, I learned that the solution involves the use of
makePatternDependency to create a
Dependency from a given
rulesExtraDependencies to associate the dependencies with a specific
Advanced usage: add extra dependencies to compilers. Basically this is needed when you’re doing unsafe tricky stuff in the rules monad, but you still want correct builds.
A useful utility for this purpose is
Jasper on Hackage
Now when I’m previewing my site—or build the site in general—and I modify any scss file, it correctly regenerates the monolithic css/screen.css file. Here’s my new scss compiler rule:
match "scss/**.scss" $ do compile getResourceBody scssDependencies <- makePatternDependency "scss/**.scss" rulesExtraDependencies [scssDependencies] $ do create ["css/screen.css"] $ do route $ idRoute compile $ sassCompiler