This seems to be an often asked question, so I thought I'd try and share the approach that I've arrived at after having explored a couple of solutions to the problem. If you want to see the full code in action, check out the repo for the codetalk.io site (linking to v1.0.0 is intended, in case the code changes later on).
For some reason Hakyll
does not include its own JavaScript compiler, which makes little sense. Luckily there is a package called hjsmin
giving us Text.Jasmine
, which we will use to both compile and minify our JavaScript files.
To get hjsmin
0.2.0.1 working with stack
, add hjsmin == 0.2.*
as a dependency in the projects cabal file, and the following to the stack.yaml
file in the project,
1 ...
2 extra-deps: 3 4
5 ...
Now we are ready to construct the compiler itself, by jumping into site.hs
,
1
2
3
4 -- | Create a JavaScript compiler that minifies the content
5 6 compressJsCompiler = do
7 let minifyJS = C.unpack . minify . C.pack . itemBody
8 s <- getResourceString
9 return $ itemSetBody (minifyJS s) s
The code is fairly straightforward. We use the Text.Jasmine
provided function minify
which has the signature ByteString -> ByteString
, meaning it takes in the JavaScript code as string, and produces the result to a string.
Later on inside the main Hakyll
function in site.hs
, we use it as we would the other compilers,
1 -- | Define the rules for the site/hakyll compiler
2 3 main = hakyll $ do
4 -- | Route for all JavaScript files found in the 'js' directory
5 match "js/*" $ do
6 route idRoute
7 compile compressJsCompiler
8 -- The rest of your rules...
For those who aren't aware, there are other ways to write CSS than CSS. Sass and SCSS adds a lot of niceties to CSS, such as nesting, variables and mixins, and compiles to normal CSS. You can read more about that on their website.
This time we rely on external dependencies, namely the sass
tool, which can be installed with gem install sass
.
Same as with the JavaScript minification, we add a compiler in site.hs
,
1 -- | Create a SCSS compiler that transpiles the SCSS to CSS and
2 -- minifies it (relying on the external 'sass' tool)
3 4 compressScssCompiler = do
5 fmap (fmap compressCss) $
6 getResourceString
7 >>= withItemBody (unixFilter "sass" [ "-s"
8 , "--scss"
9 , "--compass"
10 , "--style", "compressed"
11 , "--load-path", "scss"
12 ])
This time we have no library dependencies, and use the Hakyll
provided function unixFilter
to call the sass
tool. An important thing is the arguments that we pass, which I'll explain briefly:
-s
tells sass
to take its input from stdin
--scss
tells sass
to use the SCSS format--compass
tells sass
to make compass imports available--style compressed
tells sass
to compress the output--load-path scss
tells sass
to look for modules in the scss
directory (if we import stuff)Much like with the JavaScript compiler, we use it in the main Hakyll
function inside site.hs
as such:
1 -- | Define the rules for the site/hakyll compiler
2 3 main = hakyll $ do
4 -- | Compile the SCSS, from 'scss/app.scss', to CSS and serve it as 'app.css'
5 match "scss/app.scss" $ do
6 route $ constRoute "app.css"
7 compile compressScssCompiler
8 -- The rest of your rules...
You can now happily compile both JavaScript and SCSS in your Hakyll
project, without much hassle!