From Hugo to R Blogdown

r
blog
Published

April 18, 2020

R blogdown gives a really easy way to post blogs containing evaluated R (and Python!) code chunks and plots. This is really handy and can drop right into an existing Hugo blog with little modification. While there are some risks about the growing dependencies on building the blog, blogdown is well design to mitigate the issues and is very easy to set up.

About 10 months ago I migrated my blog from Hakyll to Hugo (after already migrating once from Wordpress). There were three reasons, I wasn’t using Haskell anymore, I wanted a prettier website through Hugo themes and I wanted to use R blogdown to write posts. I’ve finally migrated to using Blogdown (and am writing this post in it) and it was much easier than I thought.

After reading a tutorial of using blogdown with an existing Hugo site I thought it sounded too easy. But all I needed to do was install the package in R:

install.packages("blogdown")

And then I could immediately change building my website from hugo to:

R --vanilla --slave -e 'blogdown::build_site()'

I saw a really well written warning:

Warning: You are recommended to ignore certain files in config.toml: set the option ignoreFiles = ["\\.Rmd$", "\\.Rmarkdown$", "_files$", "_cache$"]

and simply adding that to the top of my config.toml fixed the warning.

I could locally generate a preview on port 4321 with:

R --vanilla --slave -e 'blogdown::serve_site()'

Benefits

Blogdown makes it much easier for me to include the results of code snippets, including plots, in the post. While I could evaluate code manually, save the results and include it in my blogpost there are some advantages to having the generating code with the text. It means I won’t lose track of where the results came from, and someone else can even reproduce my results and enhance the code. I could even have dynamic posts that update with new data each time the site is built.

Another benefit is it uses the excellent Pandoc to convert to HTML which has lots of nice features and is familiar from my Hakyll days.

Examples

Using R markdown I can show R snippets with their results:

sqrt(2)
[1] 1.414214

Even better I can generate whole plots:

plot(cars, pch = 18)

Or even embed HTML Widgets:

library(leaflet)

m <- leaflet() %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")
m

In fact RMarkdown supports many difference language engines including Python:

x = 'hello, python world!'
print(x.split(' '))
['hello,', 'python', 'world!']

I can even include Python plots:

library(reticulate)
matplotlib <- import("matplotlib")
matplotlib$use("Agg", force = TRUE)
import pandas as pd
import matplotlib.pyplot as plt
df=pd.DataFrame([[1, 2], [3, 4], [4, 3], [2, 3]])
fig = plt.figure(figsize=(14,8))
for i in df.columns:
    ax=plt.subplot(2,1,i+1)
    df[[i]].plot(ax=ax)
    print(i)

plt.show()

Drawbacks

Rendering R markdown is slow and loading the served pages locally is really slow (probably because of the underlying servr package). This is really obvious after switching from Hugo because Go is basically built for serving things fast.

Another concern is environment management. The simplest way to maintain a website is as a set of hand edited HTML files; this is likely to last for decades (like John Baez’s finds in mathematical physics). Using a static site generator has benefits, like being able to use markdown having an automatically generated index and links between pages, but means that you have to have the site generator available wherever you use it, and switching versions might break it. Moving to R Markdown makes the environment management more complicated; to get this page working requires at least R, the blogdown and leaflet packages, Python, pandas and matplotlib. Rerunning on a different version of any package this might break the page; either silently (which I may not discover for a long time) or loudly (which may stop me from posting a new blog post).

Some processes will also download data from the internet (which may disappear), or require a large amount of data (which either has to be committed or stored somewhere it can be downloaded) or take a long time to process. This means that the process could break because of the dependencies, or be very expensive to rebuild each time.

One major ameliorating feature of blogdown is it produces the generated HTML files. The blog can then be rendered directly via Hugo without having to have R and the dependencies installed. While in general I don’t like committing generated files this kind of caching is pragmatic here.

Verdict

R Markdown gives a convenient way to quickly generate calculations and plots in context with blog material. While there are some risks about being able to rerun this, it’s handy enough for me that I’ll use it. Because blogdown generates an intermediate .html a broken environment shouldn’t break the blog.

I think I’m going to use a mixture of R Markdown, regular Markdown and Jupyter notebooks to my blog for now because they have different strengths. As I work out a better workflow with R Markdown and solve environment management I may migrate to it more.