Now that Swift is open-source and cross-platform, several teams are racing to make Swift a viable language for web development. The major frameworks, Perfect, Vapor, and IBM’s Kitura, have over 13,000 stars on GitHub, and are growing quickly! Join us as we talk about the different frameworks, their pros and cons, and an introduction for how to get started with developing in server side Swift. (Several of the frameworks are even solely for Swift 3!) Join Edward for a live coding demo and even deploy a Swift application to the cloud!
I started using Swift after Apple announced it. At that time, I was not a iOS developer (I was just a developer playing around with random things), and I immediately fell in :heart: with the language (two and a half years later, I am giving a talk here).
I work at Stormpath, a hosted user management and user storage system. If you are building a web application or a back-end, you can use Stormpath to help you build something awesome. Before this, I was at PadMapper (I built the iOS app), and I founded StudentRND, a non-profit organization that teaches students technology and how to code.
I want to discuss Server Side Swift from an outsider’s perspective, looking at different frameworks and where Server Side Swift stands. I will give a quick overview of the Server Side Swift ecosystem, popular Server Side Swift frameworks, a simple “Hello, World!” application, and then go through a live coding demo, to demo getting your Swift environment set up with Server Side Swift, coding a “Hello, World!” app, and then deploying it to the cloud on Heroku instance.
Why Swift for Web? (1:58)
Most of us have built Swift applications (or messing around) with Swift for iOS or Mac OS X. With the release of Swift open source in December, developers have been playing around with building servers, building Swift for web applications. And, why would we want Swift for web?
- Compared to several popular web programming languages (Python, Ruby), Swift is a fast and safe language. It executes as native code.
- It is a strongly typed language and, with the use of optionals, you can make sure that you will never have any null pointer errors.
- Unlike other safe languages (Java or C#), it is more expressive. It is a great way to build something quickly, while making sure that you do not go and have to make sure that you have the assistance of the compiler to help you: 1) build an application that does not crash all the time, and 2) make sure that you can speed up your own application development.
- Developers love Swift. Bringing Swift to more platforms is always exciting.
A friend is sponsored by one consultancy that builds iOS apps; they use PHP’s Laravel to build the back-ends for their iOS app and they also use Swift for their iOS apps. That one consultancy is sponsoring development of Server Side Swift because they want more flexibility between their front-end developers (who are building their mobile applications) and their back-end developers (that are building the APIs right). Getting some of their back-end developers to learn Swift allows them to utilize their developers even more effectively by moving them between the back-end and the front-end.
Four of the largest Server Side Swift frameworks that I have been merging are: Perfect, Vapor, Kitura, and Zewo.
Many of you may have heard of Perfect, if you have looked into this ecosystem. Perfect started by a team of two or three people in Canada. October or November of last year I remember they were campaigning everywhere, “when Swift goes open source, and it will, you are going to be able to build some cool stuff with it on this server”.
Perfect has the most stars right now on Github: 7200+ stars (the most popular web frameworks, Rails, Expressjs, JDjango, they are all in the 20 to 30 thousand star range on Github). It shows you how much interest there is in Server Side Swift. They are aiming to be like Rails for Swift. They are trying to make a complete framework that allows you to do anything that you want to do in Swift. They have a great set of features. However, Rails is a little monolithic (you have to do the things the Rail’s way). And it is the same thing with Perfect: they have great features, but they do only have a few ways that they expect people to engage with their software.
Let’s take a look at Perfect code (see video). You run their application, they have a http server themselves where you can run their fastCGI module and link that to Apache or NGINX. Then you would write a module that the Perfect server would run. In this snippet, we are building a “Hello, World!” Application. As a user you would go to
localhost, and this would print out “Hello, World!”. Perfect requires you to register a global function in your module, called
PerfectServerModuleInit. Then you initialize their routing handler and bind a handler to the slash route. In your routing handler, it would be a class that has one function called handleRequest. We are appending to the body “Hello, World!” and this saying, “this request is now completed”.
I have been building Node.js apps on the Server Side and, previous to that, PHP. It feels a little odd in terms of my preference for syntax, but it gets the job done.
Vapor is the second most popular library on Github (4000+ stars), and it is Laravel-inspired. Laravel is the PHP web framer, and Laravel aims to have a very expressive syntax.
When I did my initial investigation into Server Side Swift, they had great documentation. One of the creators of Vapor, Tanner, is the guy that I was talking about earlier: Vapor has two people sponsored full-time by this one consultancy. These two people are working tirelessly to build a great web framework (similar to Perfect - the Perfect team raised 1.5 million dollars to continue building and commercializing Server Side Swift).
Let’s take a look at the code in Vapor (see video), to build that same “Hello, World!” application. We will import the Vapor module, and create our application object. We are going to bind a handler to slash where we returned the string “Hello, World!”. Then we start the app and… that is all we need to do in Perfect to create our basic “Hello, World!” app.
I like this example because it shows the expressiveness of Swift. Here we are returning a “Hello, World!” string, but Perfect has this protocol that you can return a response in. You do not have to return just a string, you can return e.g. a template engine or JSON, and that is going to convert it into the right set of apps.
IBM Kitura (9:28)
Kitura is being developed by IBM. Kitura came the end of February. They are third most popular on Github (3000+ stars). IBM acquired this company called Strongloop, which is the maintainer of Express.js - it is not surprising that Kitura is also a Express.js-inspired framework. The syntax for Kitura looks similar to Vapor. We import Kitura, we create our router object, and then the router binds something to slash. In that, we send a response saying “Hello, World!”, run the http server.
Kitura syntax looks similar to Vapor. It differs in many different ways, but if you are familiar with Express, this will look very familiar.
Unlike the other three, Zewo is not the fourth most popular on Github (1000+ stars). Although there are many different Swift web frameworks (Swift on Rails, Swift on Sails, Swift Express, etc), Zewo is super modular: Zewo is composed of 50+ different packages that you can use to build your own web application. If you want to build your own http server, or if you want to build your own web application framework and you do not want to build every single component of it, you can use many of Zewo’s different libraries to customize your web server and your web application framework. Also, due to Open Swift, Zewo’s base components are interchangeable with Vapor. Hence why this talk is called Super Spectacular Server Side Swift.
Open Swift (11:35)
Open Swift has project S4 - S4 stands for Server Side Swift Standards. They have been working together on a common set of middleware, request, response, server… different protocols to use when building middleware for Server Side Swift applications. You could build one piece of middleware that would work with both Vapor and Zewo. I have also seen people from IBM’s Kitura and Perfect in the Slack channel. In the next few months, it may become a standard for all the major different server sites with frameworks.
Zewo syntax is similar to Kitura or Vapor. Because of its super modular nature, we have to import two different modules to make this work. We create a router object, we bind a handler to
/, and we respond with “Hello, World!”. I created this quick chart to show what these frameworks look like in terms of features and Swift versions.
All these frameworks have a basic templating engine set up. All these sites for Kitura also have basic ORM; you can use that to connect to your database and convert them into Swift objects. Out of these four, if you wanted to build something today, Perfect, Vapor, and Zewo are definitely fleshed out. Kitura is still catching up because they were later in the game (starting in late February). But all of these are fun to play around with.
They have different Swift versions (Swift 2.2: Perfect. Different Swift 3 versions: Vapor, May 31st; Kitura, May 9th; Zewo, April 12th). And you may wonder, why are there many Swift versions? The reason is: Swift Package Manager.
Swift Package Manager (14:28)
Swift Package Manager is only available on the development snapshots of Swift 3. Some of this comes from the fact that Swift 3 originally looked similar to Swift 2 (all you had to do was build on a Swift 3 snapshot). However, there were breaking changes being released on a half-month basis that now all the projects are on different Swift 3 versions. Also, foundation is not completely implemented. Many of these framework implementers are waiting for Swift 3 to come out for foundation to be production-ready.
I wanted to show a quick coding example of building our first Vapor app, getting our Swift development environment set up, coding that “Hello, World!” example I showed earlier, and deploying it to Heroku. Fast and simple.
Install Swift Version Manager (15:53)
First, we will set up Swiftenv. If you are not familiar with Python or Ruby, in many other programming languages, the community has a tool that helps manage your different versions of the language that you are using. For Swift, it is very similar, especially because of all the turn with the different versions of the Swift snapshots.
First, we need to install Swiftenv.
$ git clone https://github.com/kylef/swiftenv.git ~/.swiftenv $ echo 'export SWIFTENV_ROOT="$HOME/.swiftenv"' >> ~/.bash_profile $ echo 'export PATH="$SWIFTENV_ROOT/bin:$PATH"' >> ~/.bash_profile $ echo 'eval "$(swiftenv init -)"' >> ~/.bash_profile
Swiftenv is written by Kyle Fuller, who is a prolific contributor to the Swift ecosystem. All we have to do is clone his repo, move it to our own directory, set some environment variables and make sure that it gets added to our bash profile.
Install Swift 5-31 (17:10)
We use Swiftenv to install their latest development snapshot of Swift (because we are building for Vapor, we are going to install the May 31st development snapshot):
$ swiftenv install DEVELOPMENT-SNAPSHOT-2016-05-31-a
Initialize Your Project (18:12)
We create a folder, make a directory (SwiftLangHelloWorld) and use Swiftenv to set our local environment to this development snapshot. This command is not entirely needed, but you might be using different versions of Swift later, and you might be sending different versions as your default. That creates a file called
Swift-version (which specifies the version of Swift). This allows us to make sure that we are running Swift with the correct version of this project.
$ mkdir HelloWorld $ cd HelloWorld $ swiftenv local DEVELOPMENT- SNAPSHOT-2016-05-31-a $ swift package init --type executable Creating executable package: HelloWorld Creating Package.swift Creating Sources/ Creating Sources/main.swift Creating Tests/
Lastly, we run this command using Swift Package Manager and run
swift package init --type executable. That creates a basic structure for Swift Package Manager to use and for us to start building our application. First, we will create a
package.swift file, which manages all the dependencies that we will be using for this project. Second, we will create a
main.swift file (where we will be running most of our code).
Add Vapor to your
import PackageDescription let package = Package( name: "HelloWorld", dependencies: [ .Package(url: "https://github.com/qutheory/vapor.git", majorVersion: 0, minor: 10) ] )
Now that we have this project up, we will add Vapor as a dependency for our project into our
package.swift, and let Swift Package Manager download the dependency and add it to our Xcode file. I have opened this up in Sublime and you can see our
package.swift file. This is a subset of the Swift language. All that is here by default, we are importing package description and we are creating this package object. I am going to add Vapor as our dependency, save it, and use Swift Package Manager to 1) download the dependencies and 2) generate an Xcode file.
Open in Xcode (20:40)
If I run
swift build swift package generate-xcodeproj, that will start cloning the Vapor dependency, go through the Vapor dependency tree and make sure that we have all Vapor’s dependencies. It is going to download all these and generate an Xcode file. It starts out by cloning git Vapor, then cloning S4 which is the Server Side Swift Standards, and all the lovely different dependencies that we have for Vapor.
Swift Package Manager does not have a centralized repository, all we have to do is point it to git repo and it is going to crawl through and look at the
package.swift file and the tags to figure out what to download.
$ swift package generate-xcodeproj $ open HelloWorld.xcodeproj
Now we have this project, we open our Xcode project that it generated, called
SwiftLangHelloWorld.xcodeproj. It generated an xcode project. We have our
main.swift. It only has a
print ("Hello World!") statement. We will copy in that code that we had earlier. Then we will run this, “Server starting at 0.0.0.0:8000”. If I go to
Hello, World! (👏). That is how easy it was to get started with our Server Side Swift application with Vapor.
Now… to deploy to the web! (22:30)
$ git init $ heroku create $ heroku buildpacks:set https:// github.com/kylef/heroku-buildpack-swift $ echo 'web: HelloWorld --port=$PORT' >> Procfile $ git add . $ git commit -m "created project" $ git push heroku master
Heroku is a platform as a service. You take your code, initialize it with a git repository, and use git to push it to heroku. Heroku will automatically detect what type of application you have, it will compile it and run it. Heroku cannot automatically detect Swift, but you can set a custom buildpack that it can use to detect, build, and run the project.
In our command line, we will create a Git repository. We run the heroku create command. When you install Heroku, you can download a command on utility that will help you automate. This added Heroku as a remote to our Git settings, and now we can push to Heroku as a target. Then we run this command, heroku buildpack:set, and set this to Kyle Fuller’s Heroku buildpack for Swift. This tells Heroku, “this is how to detect the app and then here is how to build and run it”.
The next thing that we need to do is create a Procfile. For Heroku, barring very common frameworks, you need to tell Heroku how to run your application. We create this Procfile (just one line),
web: HelloWorld --port=$PORT.
$PORT is Port, as in the environment variable. Heroku will run it at a custom port and put it behind a load balancer [You need to change this because it would be SwiftLangHelloWorld (which would not be what this is), web: SwiftLangHelloWorld on this port]. We will add all our files. We will create it and we push it to Heroku. This might take a minute or two - Heroku does not support Swift as a native language, it will have to download the Swift binary, install it, compile and install the app [the example was not able to complete during the talk due to an unexpected error].
Is Server Side Swift Ready for Production? (25:37)
The answer is still no. Foundation is still incomplete on Linux if you want to run your own network request, you cannot use
NSURLSession as you might be used to on iOS or OS X. You will still have to link directly to C binary, as
libcurl, and make those requests directly. Managing the different Swift versions can be annoying. Swift language is making breaking changes every other release (not fun), but I think it is going to be better after the Swift 3 preview (hopefully at WWDC or soon after).
At the same time, Swift still is awesome. Server Side Swift is fun to play around with. I am excited by all the energy that I see in the community. I think Swift is going to be big on the server.
If you want to contribute to Server Side Swift in your free time, there is many exciting ways to get involved. I have personally found the most easiest way is the Vapor, Zewo, and open Swif, have Slack channels that you can join and the people on those channels are super helpful. If you want to get your hands dirty, go to their Github: they have a link to their Slack channel that you can join. You can contribute and build your own different projects (so much fun!).
Q & A (26:42)
Q: That was awesome. I was wondering if, on each request, is that
main.swift file rerun or is it the same, is there a state you can maintain between requests?
Edward: Yes, there is a state you can maintain between requests. I did not talk about the concurrency nature, but as you can see, this is one thread, it is not like Express where we are asynchronously returning something. I looked into how concurrency works for these four different frameworks; most of these are using threads, or
libdispatch canvassing Vapor is using threads. Every time a new request comes in, Vapor the application will spawn up a new thread or a new dispatch, a grand central dispatch process. And then run this code for the request. The only one that is different is Zewo. Zewo takes a very interesting approach. Behind the scenes, they are using libnl, which it brings ghost L coroutines to see. And libnl, they packaged that into a Swift package called VeniceX and in Zewo you can use coroutines for the concurrency. But this is threads.