ZOMBIE: Remote control of the DOM

Frontend and Backend

It’s pretty common the write a web application in
two parts: a frontend,
perhaps using Angular or Knockout;
and a backend, perhaps using Django
or Rails or some similar framework. The two codebases
are largely independent, joined only by an API between them, perhaps conforming
to REST principles and maybe even a Swagger or
Pact defining the API.

But that means three conjoined components already, and we haven’t even considered
the database, or any external components or gateways.
Sure, you could forego a separate frontend and just write everything as
HTML templates, but then you’d have to do actual page
loads and people would think you
were uncool (to be fair:
AJAX partial content loads
are one of the few things which are actually good about the modern web)

Compiling to Javascript

So it’d be nice to write all your code in one place instead and have the whole
thing just sort itself out: after all, computers are supposed to be good at
organising things. Projects like Haste and
Batavia and my
(long dead) Tropyc aim to compile a source
language up to Javascript to run selected parts of it in the browser.

I was originally thinking about this … I don’t know, some time
after 2006 which was when I got into Python but before 2011 which
is when the idea morphed into
Python in the Browser and crawled off to die.

Zombie takes a rather stupider, more direct approach.

zombie.js

The browser loads a dummy page with content suitable for SEO. There’s not much
interesting about that page, but it includes the zombie loader:

<script src="/zombie"></script>

That’s going to make the browser GET the zombie loader code, which looks something
like:

This tiny snippet of code creates a function Z, which establishes a connection
back to the server, passes over a message args and asks it what to do next.
The server can reply with commands to update the DOM and to run snippets of Javascript.
Those snippets, in turn, can use Z to send more messages back
to the server. The browser is no longer an independent process with its own mind:
it is a zombie, under control of the server process.

The server could be implemented in just about any language, the messaging protocol could run
over POST requests
or over WebSockets
or whatever technology the browser people come up with next. So long as the zombie
messaging protocol is agreed upon, it doesn’t really matter.

That’s horrible …

Yes, this all sounds horribly inefficient and in a lot of ways it is: your backend
is sending chunks of HTML instead of neat snippets of JSON, and there’s some extra
chatter back and forth as events occur. But the transport is compressed anyway,
and because we have control of both ends of the process, we can choose to only send
events we’re interested in receiving, not every keystroke and mouse movement.

And in return for which, we’ve reduced our cognitive load: only one code base,
no need for a build pipeline, no need to document or implement an API. The time
we would have spent on that stuff we can spend on developing features our users
actually care about.

… and insecure!

The zombie loader is indeed eval()ing code (more or less), and that sounds like
a scary thing, but that code is coming from the same server from which the loader
was loaded: you’ve already been bitten, you might as well start staggering around.

… and what about RESTful and Microservices and so on?

So rather than your HTML5 frontends consuming your microservices directly, they
talk to their Zombie BFF (Backend for Frontend)
which talks to those services on their behalf: easy peasy. The BFF layer doesn’t
hold much state, maybe just a little bit of per-user cache and session info, so can
be scaled out horizontally, geographically dispersed and killed off on a whim.

Why Zombie?

At this point, the BRAINS! jokes are just writing themselves.
For the real inspiration, see
Ophiocordyceps unilateralis
but there’s no way I’m naming a project that.

zombie.py

To be continued … very sketchy first experiments for a Python implementation of
Zombie on GitHub