This is a fun experiment to demonstrate what can be achieved with the Elixir macro system. It's
a rudimentary blogging system - posts are simple Markdown files stored in the posts folder.
Visiting /some_post_title will eventually cause the PageView module to call
PostRenderer.render("some_post_title.md"). Now, here's the fun part - that function has been
defined with a macro in the PostRenderer module. At compile time, we go through every file in the
posts folder, render it to HTML, and then define a pattern-matched function that simply returns
the result of the render for the given filename. At runtime, calling the render function has the
performance cost of returning a constant (AKA blazing fast).
New: posts are now rendered from Markdown into HTML concurrently, courtesy of Task.async. Great
performance at runtime and faster compile times? Yes please :)
This silly example will just raise an error when trying to render a post that doesn't exist in the
posts folder, but you get my point. A quick note in case you try playing around with posts: when
you create a new post or modify an existing one, you'll need to stop the Phoenix server and run
mix do clean, compile so the macro gets a chance to run again. That could potentially be avoided
with the @external_resource module attribute, but I haven't tried using it.
To start your Phoenix app:
- Install dependencies with
mix deps.get - Create and migrate your database with
mix ecto.create && mix ecto.migrate - Install Node.js dependencies with
npm install - Start Phoenix endpoint with
mix phoenix.server - Visit a sample blog post