Pre-render pages and serve them as static assets?

In my application I have some pages that have 100% static content. I think it is possible to pre-render them at mix compile stage and put the resulting html files in the priv/static dir and serve them with Plug.Static or even with nginx directly.

Before I go down that route I want to ask the forum for opinions. Has anyone done that? If so, are there something I need to be careful about?

1 Like

I’d be questioning if it’s actually worth the effort. Plug.Static is nice to serve whole folders, but less so when you need to deal with pages mounted in various places of your application. For serving through cowboy it might actually be faster to serve a static template, which is already in memory than reading a file from disk.

2 Likes

You are right, it probably does not make any difference on performance one way or the other, at least for me. The first problem I encountered is although the content is static, it has to reference other assets such as:

Routes.static_path(@conn, "/css/app.css")

I don’t want to hard-code the path because I still want to make use of the nice digest that phx made. however mix phx.digest comes after mix compile so that is a circular dependency right there.

I will just table this idea now. It could make a difference if there were thousands of static html files.

I was thinking about implementing this for my blog actually. Was going to go with a custom mix task that would be ran after mix phx.digest like mix gen_static to render the static pages by looping through the templates, calling render on them, then storing the output in the static assets directory. If their name is mapped to a specific path variable in a route through an index page then its just accessing the right file using the static_path. Like the posts/:post_name route would map to a file in Routes.static_path(@conn, "/static/#{post_name}", where post_name would be something like 2020-02-03-first-post.html. It only really makes sense though because I am using earmark to write posts in markdown, render them to HTML, and server them through a ‘dummy’ eex template. Which isn’t the fastest way of doing it…

That being said, haven’t had the time to actually finish it :smiley:

1 Like

If your site is completely static like a blog, maybe the best way is to use a static site generator like hugo or jekyll. There is no need to re-invent the wheel. However, If your site is dynamic but with a sizable portion in static content, it does make sense.

The chicken and egg problem is still here: The static pages need to reference the digested assets, but the static pages themselves need to be digested as well, because they are also static assets. Even without static html the asset referencing asset problem is still here, for example a chunked webpack javascript file will reference other javascript chunk.

In the static site generator world, they give up on the digest idea. However, static host like Netlify and Vercel maintains http etag for each file automatically to solve the cache invalidation problem. Maybe that’s the way to go. Can Nginx generate/maintain etag? Can Cowboy generate/maintain etag? If so, do we really need digests?

1 Like