A development blog.
Hello. I’m trying a new thing here, a semi-regular blog detailing the work I’m doing on a specific project. Namely, Hybrid, my attempt at implementing Service Workers inside an iOS app. Normally we write up all our Lab projects on Medium, but waiting until I’m finished before detailing everything isn’t going to work here - there’s just too much going on.
It’s for me more than it is for you - I’ve been reading through my old code and struggling to remember why I made some of the decisions I did. The usual answer to that is “write more comments in your code”, and that’s fair, but it doesn’t capture the overall thinking that you’re doing about a project while you write it. But hopefully this will also be a way for people to discover more about this project as I chug along with it. Updates will be sporadic, as this isn’t the main project I’m working on at the lab right now, but whenever I have some free time I’ll be piecing it together.
What’s the current status of the project?
Messy. It started off as a hacky experiment and sort of ballooned out from there, so the code is awful. But it is live in the App Store as the Guardian Mobile Innovation Lab app, and it does indeed download, register and load Service Workers (using JavascriptCore) and allow you to do things like post messages from the (WK)Webview your content is in, and even receive notifications. But like I said, it’s an utter mess. So I’m rebooting it. That doesn’t mean I’m rewriting all the code from scratch, just that I’m starting a new project, then copy and pasting in various bits and pieces as I need. I’ve got a few aims with this reboot:
-
Organised code. Hybrid was also my first decently-sized Swift/iOS project, so I wasn’t too clued in on the best ways to structure a project. Right now, all the code sits inside one project, and I intend to change that. Partially for my own sanity, but also so that specific portions of the code, like the Service Worker implementation (separate from any UI-facing webview stuff) could possibly be separated out and embedded into an existing app at some point.
-
Tests. I started with the best of intentions, and created a test suite. But then deadlines appeared and I rushed, and now half of them don’t even pass, to say nothing of the vast amounts of code that have no tests at all. That came back to bite me when we did use the app to experiment with live video notifications, as it turned out the published version of the app didn’t let me update a cached worker. I don’t want to do that again.
-
Use new functionality in iOS11. One of the hackiest parts of the current project is how it actually serves content. In order to implement the Cache API and the fetch event, it actually creates a new local web server for every domain, and points the web view to it. That’s wasteful, and also has enough security implications to worry me deeply. iOS11 introduces the ability to register a protocol with WKWebView and manually provide data in response to requests, which will be much, much cleaner.
-
Make a ServiceWorker implementation that’s as tiny as possible. One difference between iOS and the web APIs that I’m going to struggle to solve is that the contents of an iOS notification are decided by the server and presented immediately, wheras on the web you use the Push API to send data, then construct the notification inside the worker. iOS 10 introduced Notification Service Extensions, which allow you to intercept the notification before it’s shown and alter the content. But, they have very, very tight memory requirements. Right now, just trying to spin up a worker is enough to cause it to hit the memory limit and terminate the process. But the Service Worker implementation uses third party frameworks like PromiseKit and FMDB, and I’m hoping that if I can strip all that out, it might be lean enough to execute in. It probably won’t be, but a small worker implementation also lends itself to having something that other apps can embed, so it’ll still be worth it.
Anyway, stay tuned.