Mikito Takada: Adventures in Single Page Applications
You can read the outline of the talk here.
Why do we write single-page apps?
- fast, responsive UI (latency kicks in if rendering is calculated on the server)
But we still need to solve the following problems:
- lower productivity: write once for server, once for client
- testing is harder, e.g. with DOM/browsers
- initial load time (time to interactivity) is worse, we need to load more at first
- pages cannot be crawled (without the extra server code as above)
What is the ideal codebase?
In the physical world, we can build great things, but different systems are not that interconnected as in software. For example: a toilet flush failure won’t launch the missiles on a carrier. Code complexity comes from code parts that have remote inputs or remote effects.
For a better codebase:
- Things should be loaded independently.
- Things should be tested independently.
- Things should break independently.
What’s wrong with MVC?
Controllers worked well in the server-side world: one request, one response, working with a throwaway state. With single page apps, we’ll keep that state, so we might as well invest in a generic mechanisms rather than writing housekeeping code each time.
We need to mediate by mechanism rather than by case-specific codes. Each thing needs to have observable events and public API.
The controller is a familiar word that makes writing glue code sound like a design pattern. We need to get rid of the MMMMMVVVVC concept in single-page applications.
How should a module or package look like?
A module is an independent piece of code that hides implementation details behind an interface. A package is a directory of modules - behind a single public interface. From the browser’s perspective, it should be a single HTTP GET.
During their loading, a module or a package should not modify any global state. Initialization code should be separate, as it might be environment-specific and breaks reuse.
How can we improve rendering/templating?
A page used to be a series of string-processing tasks, but it is really hard to bind DOM events to the generated structures, especially with nesting. Instead, we should focus on declarative views and bindings.
Mikito Takada presents a key idea behind his actual project (view.json). If we abstract away the DOM implementation, the rendering can be the same on the server- and the client-side, allowing even a fast state transfer between the two.
View.json compiles the template into object prototype declaration that can be instantiated as an object. Views are objects not strings, they intercept events, they call the (mock-)DOM to update it.
What is required for instant interactivity?
- "What is the least we can load?"
- "What is the least processing we can run?"
Load only one package ('core'+1). If possible, start running on the server, continue running in the browser (e.g. state snapshots with the fake DOM). Pre-render first HTML parts on the server, display it in the browser, continue full processing afterwards.