We’ve spent the past 4 weeks discussing DSLs in Swift, and yesterday it all culminated with the open sourcing of swift-html, our new Swift library for building type-safe, extensible and transformable HTML documents. The design of this library has been battle-tested for the past year, for it powers every single page on the Point-Free site. The entire code base of this site is open source, we built it from scratch in the functional style, and we even gave a tour of the site on a recent episode.
However, we know that most people are not going to adopt all of our techniques in building a Swift web app (at least not yet 😉), and so we want to make sure that the HTML view layer is accessible to everyone. That’s why today we are open sourcing a new micro library for bringing our swift-html library into any Vapor web application, one of the most popular server-side Swift frameworks available today!
Typically a Vapor app renders HTML views through the use of the Leaf templating language. It’s design is very similar to that of Stencil, which we discussed in our episode comparing DSLs to templating languages. As an example, we could create a Leaf template by saving the following to a .leaf
file:
<ul>
#for(user in users) {
<li>#(user.name)</li>
}
</ul>
And then from a route you could render this template with an array of users by doing the following:
router.get("hello") { req in
return try req.view()
.render("UsersTemplate", [
"users": [
User(name: "Blob"),
User(name: "Blob Jr."),
User(name: "Blob Sr.")
]
]
)
}
This templating language is flexible, easy to use, and great as a starting point. However, it has all of the same problems that we covered in our last episode, including lack of type-safety, no good tooling support (autocomplete, syntax highlighting, refactoring, debugging, etc.) and it can be more rigid that what we are used to.
Luckily Vapor makes it very easy to support other methods of rendering besides Leaf, and that is precisely what our new library helps with. Simply add the following to your Package.swift
file:
.package(
url: "https://github.com/pointfreeco/swift-html-vapor",
from: "0.1.0"
),
""",
And then you can return a Node
value from a router endpoint and it will automatically be rendered!
import HtmlVaporSupport
import Vapor
let app = try Application()
let router = try app.make(Router.self)
router.get("hello") { _ in
html([
body([
h1(["Type-safe Vapor HTML"]),
p([
"""
This is a Vapor plugin that allows you to write type-safe, \
transformable, composable HTML views in a Vapor app!
"""
])
])
])
}
try app.run()
And that’s all there is to it!
If you are building a Swift web app using Vapor we hope that you will consider using our swift-html-vapor plugin as way to create your HTML views. We think you’ll be pleasantly surprised how nice it is to code up views in Swift and Xcode, and there are lots of opportunities for code reuse and composability when building HTML views in this way.