What Web Framework Should I Use in Clojure?
In this guide, I describe the available Clojure web framework options and give my recommendations.
Roll your own stack from recommended libraries (check out my tutorial) if you are just learning. It will be the best way to understand how everything works.
Use Pedestal if you want a production-tested foundation on which to build your application.
Use Luminus if you want the flexibility of rolling your own stack without the work involved.
One question that beginners ask me in Clojure is "What web framework should I use?" This is a good question. In Python, there's Django. In PHP, Drupal. And of course, in Ruby, there's the king of all web frameworks, Ruby on Rails. But in Clojure, this is a difficult question to answer. Even deciding what is a framework and what is a library can get complicated. We will have to address that first.
What is (and isn't) a web framework
For this guide, a web framework is a collection of code and dependencies that provide a holistic approach to building a web application. This definition rules out several libraries that are commonly called frameworks, such as Compojure and Ring, since those don't give you an approach by themselves. However, there are still several great contenders which I consider here.
Because rolling your own stack is a common alternative in Clojure to using a pre-built framework, and it is a holistic approach (namely, build your application from existing libraries), I consider that in the recommendations as well.
This guide aims to give strong recommendations for web frameworks for different needs. Here are the criteria I examine for each framework:
Does the framework have easy-to-follow documentation? I look for beginner tutorials through advanced topics.
A large, active community is essential for a framework's viability. A large community can more easily provide support, keep dependencies up to date, and build a complete solution.
Another critical factor is the age of a project and how long large-scale sites have used it in production. I prefer older frameworks that significant sites have deployed.
Since a framework must provide a holistic approach, we must consider the approach. How does the framework approach building an application?
When your application is ready, you need to deploy it. What deployment options are available? A wider variety is better.
Is Clojure good for web development?
Yes, Clojure is great for web development. Here are the main reasons:
- JVM deployment options. Clojure can deploy anywhere Java can.
- State-of-the-art servers. Clojure can leverage Undertow and Netty, some of the fastest web servers out there.
- Clojure is data-oriented. Most web applications are about storing and fetching data in a database and transforming its structure. Clojure shines at that.
- HTTP is stateless, which fits the functional paradigm.
- Clojure concurrency makes multiple connections and shared resources a breeze.
Roll your own
It feels weird to say this, but the best option for beginners is still to roll your own. Building a web application from libraries is not as difficult as it may seem. The more robust, pre-built frameworks have made hundreds of decisions about the stack, but they require you to understand the legion of libraries they chose.
Rolling your own stack is good for learning how the web works. The best Clojure programmers I know have excellent knowledge about HTTP, web standards, and best practices. I cannot say the same for Rails programmers. Clojure programmers deeply learned how the web works by building the stack themselves.
Another benefit of rolling your own is that it gives you complete control to support or not support a given feature. Pre-built web frameworks make a lot of things super easy. But sometimes, something that should be easy becomes hard in the framework.
The biggest drawback to building a stack from libraries is that you must make many decisions for yourself. There are tons of libraries, and choosing among them can be difficult. One consolation is that Clojure libraries that fill the same role are usually compatible. It is relatively easy to switch libraries if you find that one doesn't work for you. For example, swapping routing libraries is straightforward.
When you want a complete solution, you will arrive at something like the more robust frameworks if you continue to build it yourself. I would recommend switching to one of the other suggested solutions rather than making a complete framework. Luckily, switching between them is easy since they all work on the Ring standard.
Pedestal is a mature set of libraries, created initially by Cognitect for developing modern, streaming web applications. They built it around long-lived connections that allow you to stream data from the server to the client over time. To support that feature, Pedestal invented the idea of interceptors, which give you a way to define pipelines of asynchronous steps that your request goes through.
I recommend Pedestal because it is mature, has an active community,
supports various deployment options, and has good support for web
applications. The two knocks against it are its documentation and lack
of a unifying approach. It has some guides that will get you through
Hello, World! applications. But I have not found anything that
will explain how to put together a complete application.
Pedestal's approach provides the low-level groundwork you will need, like a pedestal on which to stand a bit taller than starting from scratch. That groundwork is vital, but a lot is left to the developer to choose and build themselves. For example, it purposefully does not have an HTML templating solution. It calls that "API-first." I would expect a complete web framework to have a solution for creating HTML.
Despite these issues, I recommend Pedestal as a solid and flexible foundation on which to build applications.
Luminus is essentially a template project. You create a new web application from that template, setting everything up for you. Luminus gives you some options for the template, but in general, its approach is to make the choices for you---sometimes providing Luminus libraries and sometimes using existing libraries. When it creates your project, you will have a complete web stack that is yours to build on or modify as you see fit. The main advantage is the unified vision that guides the choices of libraries.
Luminus aims to provide everything you need to write web applications. You get everything: routes, session management, ClojureScript compilation, database migrations, etc. It all comes pre-configured to get started with your application logic right away. Think of Luminous as the set of libraries and configurations you would build yourself over ten years of work on an application. You might not need them at first, but eventually, you will want security, logging, and internationalization, among other concerns. Luminus gives that to you with one command.
The main drawback with Luminus is that many of the libraries are exposed directly. Yes, that gives you the power to configure them as you will. But it also means you have a lot to understand if you want to build on the default behavior. Luckily, the documentation story is excellent. There is even a book which documents the recommended approach to building a web application using Luminus.
In addition, it has been around for years, large applications use it, and it has a variety of deployment options.
Other frameworks of note
These frameworks are interesting for their innovative approaches.
Fulcro is a fullstack solution. It uses React on the frontend, but it has a complete data model from client to database. If that kind of unifying vision is appealing, give it a try. There is excellent documentation, and it is still actively developed.
Duct is a Leiningen template that approaches building a web application as a set of configurations. For instance, in Duct, routing is a configuration. Migration is a configuration. Using this unifying, data-oriented approach, you build a web application that you can reload deterministically. The framework seems to be getting traction.
Tadam has configured several existing libraries and created a standard directory structure to make writing simple sites easy. It is still new but active.
Coast on Clojure gives you a full solution (database to serving HTML) while focusing on keeping things simple.
Hoplon is a fullstack solution with an interesting approach. The frontend part compiles ClojureScript and lets you build interactive components that use a spreadsheet-like dataflow model. It can connect to the backend by calling functions that are proxies of functions on the server. This model lets you bypass the whole routing situation. Development on it is slow.
I do not recommend these frameworks because they have not been actively developed for too long and never got enough traction. I have not evaluated them on technical merits because I wouldn't recommend them solely based on their inactive development.
People often call these projects frameworks, but they do not meet the definition of "providing a holistic approach to building a web application." I have not evaluated them here.