Can Swift replace Front-End or Isomorphic JavaScript?

Mateusz Stawecki
7 min readApr 25, 2016

--

Call this crazy or premature, but since everyone is asking themselves “can Swift truly run everywhere”, I’ve decided to explore the opportunities browser-side, not just server-side.

Servers, Android and beyond!

Going open-source was the best thing that could’ve happened to Swift.

Many iOS developers held off embracing Swift initially due to changes in syntax, debugger issues and a mostly Obj-C codebase in all apps built pre-Swift (just search for any respected iOS developer on Twitter and add “Swift” to find out). Rightly so, it’s hard to justify the cost of switching with the primary reason being novelty.

However, open-source Swift means countless opportunities. During the WWDC2015 Keynote, I’m sure many developers felt same as me that we’d soon start seeing Swift in small web services and native platforms beyond iOS and OS X. Anyone who’s spent a lot of time having to re-write large chunks of code just to port some functionality from one platform to another has seen a light at the end of a tunnel that day.

Many are still holding off, but the tangible proof of Swift finally running on Linux has gotten the whole community particularly excited. Since then we’ve seen a number of promising web frameworks and a merged PR of Swift’s Port to Android NDK, but why stop here? Could code re-use be beneficial in the browser and how do we do this?

State of Web development

The web vs native community couldn’t be further apart. With only a few exceptions there are almost no common technologies for Front-end Web Development and Native app development (not counting WebViews). Except for “hybrid” development efforts, “web vs native” is almost an all-out war.

We use completely different tools, IDEs, languages and the way we implement the UI couldn’t be more different either. Overall this has split development into 3 segments:

  • Back-end development — REST/JSON/XML APIs for Native Apps and JavaScript powered websites, and of course straight page rendering.
  • Front-end development — HTML/CSS templating and client-side JavaScript or Isomorphic JavaScript.
  • Native development — Obj-C/Swift on iOS utilising iOS Frameworks. Java on Android utilising its SDK.

With Swift code re-use on the back-end, already being a huge step forward, using Swift on the Front-end seems to provide little benefit. If you choose the “Fat Server/Thin Client” approach: render pages in Swift and keep all of your logic server-side, trying to re-use any Swift code on the Front-end seems to be pointless. Especially since JavaScript and its relatives ES6/7 and CoffeeScript are well established as the languages of choice for Front-end development alongside a vast collection of cross-browser libraries. However, things look a bit different when using the “Isomorphic” approach.

We used to have two choices:

  • Fat Server/Thin Client — keep things server-side and render all requests as either full or partial pages.
  • Thin Server/Fat Client — keep the server light, render things client-side thus making the pages more dynamic.

Now there’s a third choice:

This is a really exciting progression, because it means that you don’t have to make the thin/fat compromise, you’re more likely writing even less code, your website is fast, SEO-friendly, yet still dynamic. The main limitation here is included in the title: Isomorphic JavaScript. Isomorphism can be achieved thanks to JavaScript being able to run on both the server (Node.js) and the browser. So what about Swift? Would it be possible to remove JavaScript from the codebase and check all of these boxes in addition to powering your native app with Swift?

Coding for the Browser

The browser might not be that far out of a reach for Swift. Simply look at the skyrocketing popularity of ES6 — successor to ES5. ES6 is used in production now thanks to “transpilers” like Babel.js, regardless of being unsupported by most browsers and requiring an “extra step”. Pre-processing JavaScript and CSS was already a common practice before ES6. Front-end devs run build workflows using tools like grunt, browserify, webpack. Not just for live release optimisation or minification, but during development as well. Now developers are flocking to ES6 for its simplified function syntax, support for classes, ability to import modules, template strings, related extensions like JSX and much more. These killer features are worth paying the price of transpiling. These are also some of the features that happen to exist in Swift.

Transpiling

Experiments with transpiling Swift to JavaScript have already kicked off: ShiftJS. The project unfortunately is early-stage with majority of Swift features missing. Not to mention any features and changes that will likely come out in June 2016.

Transpiling with http://www.shiftjs.com/

The more settled Swift is, the more feasible it becomes to maintain a transpiler, but there’s certainly much left to be done to achieve full compatibility. With a growing level of complexity, it might be better to look towards an LLVM-based solution.

Compiling

There are documented attempts of using Emscripten (an LLVM-to-JavaScript Compiler):

The team from PSPDFKit has shared their experience on achieving cross-platform code re-use with Emscripten to cover iOS, Android and the browser. Since their efforts started in 2014, the language of choice for that was C++. Assuming Swift can eventually compile to JavaScript with Emscripten, this solution seems entirely feasible. There are still some hurdles to overcome regarding dependencies and frameworks included in Swift projects (more on that later).

Accessing the DOM

Some may argue that Swift on the Front-end means having to tackle the ugly issue of manipulating and accessing the DOM. You don’t want to end up writing jQuery code in Swift. Fortunately, popular Isomorphic JavaScript projects React and JSX are proving that direct access to the DOM from your application code is not only unnecessary, but counter-productive. React handles the actual DOM changes for you, so you can keep your code clean and efficient.

React and JSX — a Timer updates its DOM indirectly by calling “setState()”

No surprise many emerging back-end frameworks are similar to Express.js, they are using productive and proven patterns. Swift doesn’t have to re-invent web development, it can borrow a lot of good ideas and learn some lessons from Node.js, React and ES6 to avoid any mistakes made in the past. I’d argue the same for potential Front-end solutions.

Make no mistake: templating and DOM are issues that are already coming up for Swift-powered web services.

Disclaimer: this is Obj-C, but I’m confident a lot of Swift servers will start with this.
We’re almost automatically following the footsteps of Node.js as a result.

Legacy Code

As I’ve mentioned before, Obj-C is still abundant in iOS/OS X projects. For transpiling or Emscripten to work, all Obj-C would have to go. Right now we’re still enjoying being able to mix our codebases. This includes a large number of commonly used dependencies, however an increasing amount of libraries driven by the usage of Swift Package Manager are going pure-Swift.

Frameworks

We’re still just getting into the Swift framework wars. Express.js emerged in 2009 and became a part of the Node.js Foundation this year (2016). It became the most popular web framework for Node.js earlier than that of course, but there were a number of other promising frameworks around. The term for “MEAN stack” — another popular pattern — was first coined in 2013.

I imagine a Swift Isomorphic framework would have to be built on top of a reliable HTTP-server framework and an ORM library compatible with both Linux and native mobile platforms.

Dependencies

Any dependencies you’re planning to use on the Front-end would have to transpile or compile as well. This includes Foundation. While the Swift port is designed for portability, it’s still in the works. There is some risk in how large the output would end up being with all dependencies statically linked and distributed through your website. To be fair, this is already happening in the JS world with webpack and browserify, so I suspect this is a matter of how efficient that process will be.

Other Constraints

Swift is not designed to run on the Front-end. Even when you transpile to JS, you still have to deal with the event loop, HTML5 APIs and many other quirks that are tied into JavaScript. Similar architectural challenges would face Google, if they actually decided to switch to Swift as a first-class language for Android. I’ve taken the rumours with a pinch of salt for two reasons: Swift is still rapidly evolving, Android SDK relies on Dalvik (would Swift compile to Dalvik or would an Android APK contain a native binary and a Dalvik fallback?). While it might be feasible, I don’t expect any announcements until Google is confident about solving these challanges.

For now…

I’m not planning to run any Swift in the browser (in production) anytime soon. However, I wouldn’t dismiss this opportunity completely when thinking about the future. After all, running JavaScript on the back-end used to be a laugh-worthy idea. Now, isomorphic frameworks are proving just how many unexpected benefits that idea can bring. Same potential benefits may apply to Swift. Simply imagine that your application needs only one language to run on the back-end, front-end and natively on mobile.

A rough representation of such model. The framework would be responsible for rendering and managing dynamic features on the Web (removing any need for bespoke JavaScript logic) based on defined templates and components. On iOS it should still allow for a custom UIKit implementation based on iOS-only UI code and XIBs.

--

--

Mateusz Stawecki

CTO/Co-founder @Tapjet - app creation platform powering apps like iMore, RelayFM, Cult of Mac Magazine and more! Passionate about apps, web and mobile.