Flutter Is About To Win Over the Web
Websites today, including the one you are using now, are written in HTML, JavaScript, and CSS. You probably read that and think to yourself well, yeah, that’s patently obvious. If I told you to create a website without using any of these three technologies, you would probably have some questions.
And yet, throughout the course of history, we’ve had many players in this space. We’ve had Flash, we’ve had Silverlight, all competing technologies that have attempted to shave off a slice of the browser market, to let the developer use different techniques to create a website. But none of them have really ever taken off.
So how is it possible that I am coming to you, dear reader, and telling you that there could yet again be a competitor in this space? Especially after literally none of the other players in this space have gone anywhere, despite years of effort?
Well, let’s take a minute to appreciate the things that these past attempts have had in common, namely:
- They needed a browser plugin to run. They normally need a platform-specific browser plugin to run on a targeted platform. Silverlight is a good example of this — at the time, people who use Linux couldn’t watch Netflix, as the site depended on Silverlight (which wasn’t available for Linux). Sure, there were open-source alternatives, but nothing first-party.
- They introduced security vulnerabilities. Flash was notorious for this (with over 1,000 known vulnerabilities). The browser would have to load a plugin to display the content, and at that point, none of the security safeguards of the browser mattered, as the plugin had complete access to the host computer.
- The performance was not as good as pure HTML. In terms of whether it was faster to load a plugin and display some text, it was always faster to just do it in raw HTML and CSS as opposed to trying to load a plugin to display some content for you.
- HTML5 came, and CSS improved. Suddenly, creating beautiful, involving experiences wasn’t impossible. Better still, browsers that hated standards, used weird hacks, or used vendor-specific implementations instead of their CSS equivalents (like Internet Explorer) were killed off.
All of these things made the choice to create a new web app in native HTML easy. After all, if the technology that you used to create your web experience got deprecated, and stopped receiving security fixes, then there would be no option but to rewrite your app from scratch in a new, supported language. But how did we get here in the first place? How did HTML become such a mainstay in today's thriving internet?
The Dawn of a New Era
On the 6th of August 1991, the web went live to the world. Then eventually we had the so-called dot-com bubble come and go. Consider for a moment that the web only came into existence for public use in 1991, and then nine years later the dot-com bubble burst, costing an astonishing $1.7 trillion. That means that the dot-com bubble cost about as much as 15% of the United States’ GDP that same year.
We’re in that part of history because that’s about the time when the web was starting to become more and more formal, and the way we were writing websites were becoming more standardized. Over time, we gained standards like HTML4 that we could use, and these standards ensured that the HTML you write in your part of the world will work for most, if not all, HTML interpreters. Cascading Style Sheets (CSS) also entered circulation in 1996, and the year before that, JavaScript also entered the scene. Can you imagine seeing or using a website with no JavaScript or CSS? It would not be an enjoyable experience, that’s for sure.
But throughout all of history, some things with the web stayed the same. To be fair, a lot of it had to: You would never want to introduce breaking changes to the HTML standard without an extremely good reason for doing so, so changing large swathes of how the web works in future versions was probably never going to happen. This left us with the web as we have it today, and what does that include?
The document
When the web first came into existence, people were not using apps as they are today. Some of you may remember using terminals that acted as thin clients, giving you a physical connection to a mainframe on the other end of the physical connection. The “apps” (if you could call them that) that people had were little more than lines of text on a screen.
People were used to dealing with things as documents, as physical pieces of paper in their hands that they could peruse. It comes as no surprise then that the basis of HTML pages is to produce an HTML document. If you’ve ever used any JavaScript, you will be familiar with functions like document.getElementById()
. Everything that you do on a webpage is to produce and then transform the document.
Traditionally, most webpages are too high to fit in one viewport. So the user would have to swipe through the page with their finger or scroll with the mouse. I can’t think of a website that I use today that fits neatly into the users’ viewport (certainly not this diatribe), so the developer would always be guaranteed that there would be some part of the page that would either be above or below where the user was currently looking on their page.
But still, you would want certain parts of your webpage to stay in a certain position or align in a certain way. You start using things like position
in CSS to control where your elements are laid out. There’s a tonne of CSS properties (520 to be exact), and as the name would imply, these styles cascade into their child elements. When you are trying to get a particular part of your document to look a certain way, it can get fairly chaotic. If you are using an existing styling framework like Angular Material, then it also gets pretty zesty, as you start to override the built-in CSS to achieve a certain look that you are after. CSS lets you override this by using !override
, but once you start doing that, the battle is largely lost. If you’re reading this and thinking to yourself “What? This guy sounds like he is hopeless at CSS,” then that’s okay and I wouldn’t fight you on that point. But when your designers are chasing a certain look, the CSS can get pretty complicated.
Learning the languages
In order to create a simple website, you need to be across three separate languages, and that’s purely for the website itself. That’s HTML, JavaScript, and CSS. Your website has to look and feel great, and it can’t do that if you don’t know how to write performant JavaScript or if your CSS styling is bad.
If you actually want your website to do anything, then you might use a framework like Angular or React. As you start to bring in packages via npm, the size of your app starts to grow, so you will also use a bundler like webpack to tie all your packages together and minify them appropriately. Webpack is a topic in itself (and a huge one at that) but it’s a worthwhile topic to consider and does form a considerable part of building web apps.
Bundling and transpilations
Once you have your website and you have your packages, you need to use a bundler to bundle up your client app and to make sure that it works in their browser. Depending on what browser they are using, you’ll also need to “shim” in certain features so the user’s browser can actually use your website. If you’re using a language like TypeScript, webpack also transpiles from this language into JavaScript.
Nothing about this is inherently bad, but it is very complex and has a lot of moving parts. If your website breaks, did you mess up the code, or did the minification break it, or did webpack not include it properly, or did the transpilation process introduce a problem? These complicated pipelines can introduce difficulties in debugging or finding the root cause of issues in your app.
How Is Flutter Any Better?
If you’ve heard of Flutter, you’ve likely heard of it in the context of phone app development. So how on earth does it apply to websites? Well, with a normal HTML webpage, you deal with the page as a document. In Flutter though, the “page” (or what the user interacts with) is actually drawn to an HTML canvas. Flutter actually controls every pixel that is drawn to the screen and doesn’t use HTML, JavaScript, or CSS to define any of its look or logic. (Technically speaking, native Dart code is transpiled to JavaScript through dart2js
, but no business logic is actually written in JavaScript.)
You’ve likely picked up two things alarming with that sentence. First, no HTML. Second, we’re drawing everything to the canvas. I get it — it sounds weird and, at least in the case of drawing to the canvas directly, not very performant. But let’s dig into this a little bit more.
Drawing into a canvas instead of a document
The first point is that we’re not using HTML to write our webpages, nor are we writing things to a document. At first blush, this is complete heresy. But what exactly are you doing when you develop a webpage in HTML?
Well, as we covered earlier in this article, you make a document that’s too big for the viewport of the users’ device, and then they scroll. What you’re reading right now on this very page, the document height is greater than that of the viewport. And you’re scrolling through the content.
When you think about it, isn’t this kind of a weird way to design a user interface, to expect that the content will be too big vertically and that the user will have to scroll through it? What if you want the user to scroll left-to-right instead of top-to-bottom? It’s not particularly easy to express on a normal webpage.
In Flutter, if you want to make a particular bit of content horizontally scrollable instead of vertically scrollable, that’s as easy as wrapping the widgets in a SingleChildScrollView
. You can also specify the direction of the scroll itself just as easily, whether it should scroll on the vertical or horizontal axis.
Because Flutter is based on the concept of laying out your page in individual widgets, not drawing a document to the screen, developers are afforded more control over exactly how they want to layout their applications.
Sticking with one language
As previously mentioned, creating a great website means that you have to know HTML, JavaScript, and CSS. It also means that your knowledge doesn’t transfer between these languages and you can’t reuse any of your JavaScript knowledge in HTML, for instance. HTML is purely your markup language, CSS is purely your styling syntax, and JavaScript is purely your programming language. None of these options include things like type checking, so your CSS can be complete bunk and it will just fail silently when the user tries to use your webpage.
Flutter uses Dart as its language, and all of the application’s look-and-feel and business logic is written in it. Dart comes with static type checking, and null safety is landing soon, so every line of code in your app, whether it be used to describe your app visually, give your app style, or control the business logic of your app, is fully type-safe.
Easier to layout your app
Broadly speaking, we use our websites to display data from another source: Whether that source is a database, an API, or something else, we wind up with data that we would like to display. Imagine that we have an array of objects returned from our API and you’re using something like Angular to display them. Typically you would load those objects into the backing component, and then use *ngFor
to iterate through them. You’d likely attach that to a div
. Out of the box, though, for an unstyled div
, it would look pretty plain. You probably want the items in that list to appear in a column or a row, so you’d have to involve some CSS or flexbox in making that happen.
Conversely, with Flutter, you lay out your children by using a Column
or a Row
that has a children
property that accepts an array of objects. When you think about it, most of the time, you probably want your arrays of objects in a row (side by side) or in a column (underneath each other). Because you have that, you can more quickly get the visual layout that you want, before you move on to styling the individual items in the list. In my experience this leads to a quicker scaffolding and prototyping of the site, without compromising the end result.
Control over every pixel in the viewport
Because Flutter renders every pixel to the screen, this affords designers and developers great control over exactly what they want their app, or experience, to look like. Rendering every pixel to the screen sounds like it would come with a hefty performance hit, and don’t get me wrong, it's certainly not as fast as rendering raw HTML these days, but things like GPU-accelerated canvases are shoring up performance in this area.
Traditionally, designing your webpage in HTML would mean you would have to take into account the different browsers that you were targeting. In Flutters’ case, though, because you layout a Text
widget with a certain font, it’ll look the same no matter where it is shown because Flutter is controlling how that particular widget will look on a per-pixel basis.
Goodbye, webpack!
Because Flutter uses Dart, when a Flutter app is compiled for its target platform, it transpires all the dependent packages (also written in Dart) to JavaScript as well. Dart is a type-safe language and doesn’t support reflection, so the effect of this is that the compiler has a better idea of what your app invokes and what it doesn’t.
This leads to better tree-shaking and the minification of your app. Building your Flutter app for the web doesn’t use webpack because it doesn’t need it, which is a pretty strong case for Flutter in itself (in my mind anyway). There’s nothing wrong with a web pack; it’s a high-quality piece of software. But it is a complicated tool in an already complicated pipeline.
But We’re Not Quite There Yet
There’s more to the web than snazzy-looking webpages, gorgeous animations, and beautiful experiences. We really do need more than just that. We need a server-side rendering (SSR) so our webpages can be scraped by search engines for any type of search engine optimization (SEO) to be carried out. At the moment, Flutter websites are only interpretable by people, not by search engines, so that’s going to have a huge impact on how people search for and find information on your website. (People are hashing it out on this issue, and it doesn’t seem like there’s a resolution coming in the near future).
Drawing everything to the canvas also has its performance implications, but these aren’t as bad as you would think. I made a test app that makes heavy use of visual effects, and it runs at near 60fps on my MacBook. Even when you drag the sheet over the screen, it still performs okay, progressively increasing the blur on the image behind. I’m not an expert in Dart by any means, so no doubt this process could be optimized even further.
So there are a couple of key areas that Flutter needs to improve on before people would consider it for mainstream web development. But think for a moment: Flutter only really came out in the last two years, and the performance and feature set that it already has is nothing short of incredible.
What could it be then, if you could make a website that was performant, and you could use one language to design, style, and write the business logic for your web app? If we back became superfluous to your development pipeline? And if in time you could have the server-side rendering and all the SEO goodness that you have today in traditional HTML-based websites?
If you had all that, then Flutter could win the web.