Zero-Cost Dependencies
This is the final essay of a 12-part series called Distilling the Web to Zero. The web is far from done improving - particularly as it pertains to building rich web applications that are, to users, developers, and businesses alike, more desirable than their native-app counterparts. This series is prefaced by defining the biggest challenges on the road towards that goal and the 12 essays that follow explore potential solutions using concrete examples.
Motivation
Since this is the final essay of this âzero-themedâ series, it might be interesting to hear what it was that sent me down this year-long idea maze which unexpectedly became the basis for web4.
In short it was my obsession with xUI â a different approach to cross-platform UI development that can span across iOS, Android and the web. Instead of constructing a tree-based hierarchy of components and toiling to get it to operate âwell enoughâ across all platforms, xUI would instead move its abstraction a level higher at the screen-level where itâd be easier to define your UI as a set of desired behaviors. No more components; those become an implementation detail. That way, an appâs look and feel could be free to vary greatly between platforms â critically important in order to achieve that ânative feelâ and escape the uncanny valley of other cross-platform approaches. This is only recently possible with the advent of modern design systems. Previously the rules of how a UI should look and behave were too undefined and open-ended to have any hope of being implemented in such a manner. Design systems fixed the paradox of choice when it comes to the art of UI design.
This approach might be especially appreciated on the web where UI is default-unstyled instead of default-beautiful like on native mobile. Developers are forced to begin with plain black text on a blank white canvas with plain, unstyled controls. xUI would slingshot devs ahead with a batteries-included, full implementation of three design systems: Appleâs HIG, Googleâs Material and Microsoftâs Fluent. UI could be a single codebase that would differ at runtime depending on which platform your browser was running on whether iOS, Android, macOS, Windows or Linux.
Creating this would result in a giant, all-inclusive SDK like the ones you see when installing Xcode or Android Studio. The sizes of these SDKs are measured in the gigabytes. This is simply impossible to do for the web which measures its micropackages in kilobytes. The on-demand nature of webpages necessitates tiny payloads whereas native apps are known to balloon to hundreds of megabytes.
Thus the xUI dream was dead on arrival, infeasible and impractical due to the fundamentals of the web. Server-side execution (web1) couldnât offer a rich enough experience. Client-side execution (web2) came with debilitating size restrictions. And hybrid client/server architectures can only offer modest improvements to richness and payload sizes but come at the cost of ballooning complexity.
Before xUI could exist, the web needed a way to build apps with zero-cost dependencies while also achieving zero sacrifice to the user experience. This became the driving force behind the birth of web4 â a new reactive execution model that happens neither on origin servers nor on the client but exclusively on the edge by bubbling events beyond the browser, over the wire to edge-side event handlers. This would allow xUI to grow to gigabytes in size with zero impact to the browserâs payload since its DOM would be manipulated remotely.
Whereâs the webâs stdlib?
Iâve had a funny journey with web development. It began back in â99 in the era of Perl, PHP and unpredictable JavaScript. jQuery, Node.js, and even Rails didnât yet exist. But in â08, I left the web to build native apps for iOS and Android. 16 years later, I finally had the opportunity to return to web development after missing not just one but multiple transformational shifts on the web.
While I never stopped watching the web grow up from afar, itâs certainly not the same as immersing yourself in the ecosystem. Now that Iâm back, itâs fascinating to experience firsthand just how vastly different the outcomes are between web and native development.
With web development, the thing I miss most is its lack of a standard library.
Are young web devs familiar with the concept of a standard library? Iâm actually not sure; Iâm new here. Most major languages come bundled with one. Itâs not something that you have to manually include, itâs more a part of the runtime itself, built and supported by the languageâs creators/stewards. Its purpose is rooted in convenience and productivity â to include most of the tools that most developers might need to accomplish most tasks. While languages are often bundled with an stdlib, platforms usually do the same thing conceptually with an SDK. Platform SDKs are a large collection of libraries and tools to help you build apps successfully on a specific platform helping you get up to speed fast, take advantage of the best and unique parts of the platform, and (most importantly in my personal opinion) offer a sense of cohesion in the outcome of its apps. Needless to say, these standard libraries and platform SDKs can often be huge: thousands of APIs across millions of lines of code.
In short, the purpose is to help developers fall into the pit of success.
Meanwhile on the web, <button>Hello world</button>
looks the same as it did in the 90s. Unrefined. Unsophisticated. Unopinionated. Instead of falling into the pit of success, the web seems to have adopted an ethos of "find your own way."
Itâs fascinatingly different. Not bad. Just different.
I guess it makes sense how the web came to adopt this approach to tooling.
The web must remain platform-agnostic
Exactly which design system should the web adopt when web browsers are meant to operate across any and all platforms? The web, as a platform, cannot play favorites. Any attempt to default one aesthetic to a webapp would be met with criticisms of favoritism and accusations of exclusionism. Donât you just hate using Material apps on iOS or vice versa, seeing Apple-isms on Android? The only winning move is not to play. Thus, web developers are left to begin projects with basic, painfully plain UI with the full burden of inventing their own aesthetic on their shoulders.
The web and dynamic languages
Thereâs another reason JavaScript skirts the responsibilities of a standard library or app SDK. Dynamic languages like JavaScript have a notoriously difficult time trimming away dead code, i.e. tree shaking. Compilers for statically typed languages like those used for iOS and Android can effortlessly trim away millions of lines of unused code and minimize the size of their binaries. If this were not the case, native mobile developers would obsessively scrutinize every line of code Apple or Google tried adding to their SDKs.
Meanwhile, dynamic languages are better served by starting with a minimum set of APIs and adding external micro-packages one by one, as needed, Ă la carte.
This puts the responsibility of fleshing out the platform on the shoulders of the community which comes with the positive side effect of explosive innovation. Without the need for planning or permission, anybody can fill any gap they please any way they like. Indeed the web has been ahead of native mobile on many fronts, like for example, exploring reactive programming models.
While I can appreciate the value of rapid innovation, this lack of authoritative oversight has led to an ecosystem that is more than a little frustrating to use. It results in toolchains that are unnecessarily long, convoluted, and fragile. Finding the right tool for the job can sometimes feel like a full time job in itself and packages all have pet names since they cannot simply be named by what they do. It is akin to walking into Home Depot to buy a hammer except thereâs no hammer section, theyâre spread out all over and always labeled something clever like Mjolnir or remmaH.
The time it takes for a developer to become productive on the web is far greater than other platforms. It feels like someone installed stoplights on the highway where every 50 feet you must come to a complete stop, evaluate 10 new packages, learn how theyâre different and why before proceeding to the next inevitable stoplight. Thereâs always 10 ways to solve every problem and navigating the best path for your product is never ending and ever changing.
To be brutally honest, itâs chaotic. Chaotic good, for sure. But still chaotic.
None of the above is meant as a criticism. I'm just the type that gets fascinated when I notice butterfly effects in nature and I obsess about understanding the initiating minor differences that caused such majorly different outcomes.
The webâs inevitable next step
So what? The web ecosystem evolved differently than native apps. Big deal right? I certainly didnât think much of it initially either. In fact, before this project was called web4 it was called something far less significant: Dumb Shell. (I even bought the domain dumb.sh). I figured I would take a few weeks to quickly bang out a minimal library to solve xUIâs dependency-challenge by moving event handlers, state management, and reactivity to the server and bubbling events over the wire. As I stumbled through this particular idea maze, I came to discover the nature of this animal was far more profound than I thought, more than even xUI, and not just by a little. What I was building wasnât just a library, it could be a movement. It has the potential to unlock the next generation of the web.
Unblurring the line between webpages and webapps
The narrative of the past has been that webpages and webapps are not a binary concept; instead itâs a spectrum â that each website exists somewhere between the two extremes of document or app. The term PWA (progressive web app), certainly implies this.
The reason for this is twofold. One, some categories like ecommerce and social lend themselves well to a hybrid model. After all, they are essentially enhanced product âcatalogsâ or an interactive âbookâ of faces, not too far of a departure from the world of âprint,â and therefore not too far a departure from the webâs original âdocumentâ metaphor.
Apps are not documents however. For some categories, like utilities and games, forcing apps into the webâs document metaphor is akin to growing a garden in the shade and has prevented many categories from flourishing to the extent you see in native app stores. Web4 takes an aggressive stance against the metaphor of a page in order to more closely match the typical programming model of a native app. Doing this requires long-lived state which is finally possible when hoisted out of the browser and onto a nearby server.
As web4 grows, the sentiment about webapps will cease to be considered a spectrum and consolidate into one of three categories:
- web1 == documents
- executes on origin servers
- mostly long-form content
- best for informational content like academics, news, and blogs
- web2 == hybrids
- executes in the browser
- mostly short-form content mixed amongst links and buttons
- best for interactive content like ecommerce and social networking
- web4 == webapps
- executes on the edge
- focused on function not content; immersive UI with complex and partial navigations
- best for productivity and immersive use cases like utilities and gaming
Note: web3 was the webâs crypto generation. Decentralization was an important evolution for the web but is inherently headless and therefore outside the scope of this series which is very much focused on UI.
JavaScriptâs monopoly on the browser is over
Hoisting an appâs runtime out of the browser and onto a nearby server means developers are no longer beholden to a JavaScript runtime in order to provide a rich user experience on the web.
For the first time ever, frontend web developers have the freedom of choice when it comes to languages, runtimes, tooling, and ecosystems.
Some might dismiss this as old news since the web grew up in an environment of language-choice with options like Perl, PHP, Ruby, Python, and JavaScript. This misses something profound. This time the output isn't a document, it's an app! This requires a far more sophisticated runtime, something that dynamic scripting languages were never designed to support. Couple that with the fact that The Edge is a far more hostile environment to operate in where latency is the mind killer.
Suddenly ecosystems that have been relegated to the backend all this time like Java/Kotlin, C#, and Go, will see a sweeping rush to the frontend. And with them will come their incredible tooling. This excites me the most. Suddenly frontend web development flips overnight from a scarcity-mindset where packages are bespoke and intentionally minimal to an abundance-mindset where the tools are part of a large and thoughtfully considered system, standardized, industrial strength, well-supported, designed for stability, predictability, and longevity.
In no way is this a criticism of web1 and web2 creators and artisans like DHH who prefer to hand-pick a lovingly curated set of tools, perfectly suited to their project. Itâs a beautiful way to build and I love that they have that option. Iâm just excited that now I finally have the option to build webapps the way I build native apps.
Member discussion