What really grinds my gears in Flutter

9 minute read

My latest post listing reasons why I enjoy Flutter so much was a bit of a puff piece, frankly. Flutter is definitely one of the most fulfilling technologies out there, but it’s not without its flaws. Let’s discuss some of the things that irritate me the most. We’ll start with the web issues.

This is my personal opinion, and even though I have worked with Flutter for quite some time, I may be wrong in some cases. Please let me know if something is incorrect or gets fixed in the future.

Web issues

Some of the experienced Flutter developers I personally know would not select Flutter as their primary tool for building a website. It’s a bit of a different discussion when it comes to a very specific set of apps that could as well be a desktop tool like Supernova, Rive, Superlist, or Rows. However, building big scale consumer-facing… portals entirely in Flutter may be out of question.

Don’t get me wrong. I use Flutter web regularly e.g. for my presentation companion apps. In my consulting work I participated in several Flutter web projects. It worked mostly fine, but the class of problems that need to be solved is vastly different from what a typical web developer faces on a daily basis.

I suspect there’s still a long way before Flutter will feel and work equally well as classic web apps. Here are some of the most pressing issues I see right now.

Announcing my newsletter

To make it easier to never miss a new blog post, I decided to start a simple newsletter. It's called Occasional Flutter and I invite you to subscribe today!

Default behavior

Anytime you run a Flutter mobile app, you can quickly deduce this from the little things like scrolling with two fingers make it go twice as fast or rotation of the app looks a little bit off compared to a native one.

Similarly, there are things that are odd in Flutter web apps. I immediately notice that keyboard shortcuts or focus behavior are just a little bit different from what I would expect. It can be tweaked to work similarly as in a simple HTML document with Actions and Intents, but developers rarely remember to handle focus changes, space or tab behavior, cursor decoration etc. [As an exercise open any Flutter web app and press space, then open Twitter and do it again]

Some other issues worth noting are lack of proper text selection (which hopefully will be fixed with this change), not being able to find words with the browser find box, and more subtle challenges like bundle size or mobile performance.

I feel like I need to emphasize that some of the issues mentioned here are not framework bugs, but rather consequences of mobile developers building web apps. As such we tend to make mistakes not understanding how the web form factor differs from a single window mobile universum.

Tough choice

When deploying a Flutter web app you’re faced with a choice. You can either run the app with the HTML renderer or CanvasKit. By default on mobile the former option is used, whereas desktop defaults to CanvasKit. For basic usage it’s fine, but in practice the mobile experience will usually be worse. There’s no easy way to measure this without performance overlay. I noticed some of the best-known Flutter web apps just avoid running on mobile at all.

Several problems from the previous section are much more perceivable on smaller form factors, which for a client may be extremely unfortunate. Some say[1], [2], that nowadays users spend most of their online time (and thus money) via smartphones. There’s a new generation of people growing up now that mobile is their primary tool to access most of the online services. It sounds obvious but delivering subpar quality and performance is out of the question for most of the startups and disruptors on the market.

Every quarter the Flutter team organizes a survey to collect feedback like this one. They publish results on medium. Make sure to take part in the next one, whenever you see a prompt in your IDE.

Scrolling and physics

Over the last couple of months this part has gotten significantly better, but it’s still interesting to see how different the scrolling behavior is in Flutter apps compared to ordinary webpages or desktop apps. I wish I would understand the technical details more, but in essence, Flutter is emulating scrolling from scratch. This means it has to handle different scroll physics implementations per platform, various input devices, and things like scrollbar on its own. There were attempts by the community to make it nicer, as well as several issues reporting spotted discrepancies.

In this animation made in Rive I tried to visualize my interpretation of how the scrolling differs in Flutter compared to typical websites. As the scrolling is emulated, it’s Flutter’s responsibility to render elements outside of the viewport once they enter it. Therefore, the browser is not able to leverage existing techniques for preloading images or rendering text (forgive me this slight anthropomorphization of browser and Flutter 😉),

Elements like this one add up to make the general feeling of the Flutter web app slightly different than what we’re used to. It’s awesome to have such freedom when building a mobile app toolkit, but it can add a lot of work when deploying a simple webpage.

General feeling

As an example for this chapter, head over to a pretty well-executed website of Matt Carroll. It looks all right, it’s relatively heavy on the graphics, and - what’s important - it’s a typical landing page that’s a few times longer than its width. Let’s list some quirks (I hope you don’t mind Matt). On mobile, you can scroll it twice as fast with two fingers. If you pause JS execution it won’t scroll anymore. The scrollbars are not provided by the browser but painted with Flutter, so they appear only when you move your mouse near the edge. You cannot select any text. You cannot enter funny faces 🤪 to send them to Matt with a macOS emoji picker. And if you leave the website open for a couple of minutes, something else happens…

GPU load

When building the Flutter web app with CanvasKit it will get rendered mostly by the GPU [citation needed]. In some cases (like the animations-heavy landing page) leaving the app open for 5-10 minutes will make your GPU hot enough that fans need to kick in. It was especially painful when using i9 MacBook Pro with its thermal limitations, but even on new M1 laptops it happens when I leave a Flutter web open. I need to point out that it may be very specific to my workflow with dozens of Chrome tabs open and several memory-heavy apps like Slack or VS Code running in the foreground. Moreover, it can be optimized and some high-quality apps like Supernova nail it, but I decided to mention it anyway.

Reinventing the wheel

People often say “don’t reinvent the wheel”. However, if not for reinventing the wheel, we wouldn’t be able to ride on the Moon. Some of the things that the Flutter team had to reinvent allow for unprecedented flexibility and performance, but at the same time make it difficult to leverage existing APIs (e.g. undo).

I imagine it’s a difficult spot to be in for the Flutter team. The decision to make a leap into the web ecosystem meant that they have to solve a completely different set of problems than in Android and iOS realms alone. For me, the distance between mobile and web seems larger than for instance between mobile and desktop. This is why my greatest excitement in 2019 was the announcement of alpha support for macOS.

Desktop issues

When discussing desktop issues, we need to face a similar truth as in the case of the web. Flutter in its foundations was meant to be run on small handheld devices 🌌. Expanding it to cover big screens where multitasking and window management is crucial means there’s a lot to build from scratch. Just take a look what kind of details need to be taken into account to correctly handle the scrollbar on macOS.

The rise of Electron’s popularity and the examples of exceptional desktop apps built with JS/TS show that there’s still huge potential for Flutter despite its past. There are several examples of apps that deliver amazing quality and experience even though the desktop ecosystem in Flutter is just getting started.

We already have a decent support for keyboard shortcuts or deployment to stores. I can’t wait for multi window support to become something built-in. We’re getting closer to rendering platform views inside Flutter on desktop. More and more progress is made on desktop foundations such as menu bars, flavors, navigation, or input devices.

Sometimes I just wonder what if in 2018 the first leap into the unknown was towards the desktop, not the web.

Shaders and jank issue

This has been on my mind since I run my first iOS app in release. The first remarks of iOS jank issue are as old as the Flutter itself. Every couple of weeks I’ve been checking the progress on the automatic shader warm-up effort and was super excited to check out the new impeller runtime. However, some odd problems show up from time to time despite various improvements over the last 2 years.

For those who read about it for the first time here’s a quick recap.

When [the animation] shader is first used, it needs to be compiled on the device. The compilation could cost up to a few hundred milliseconds whereas a smooth frame needs to be drawn within 16 milliseconds for a 60 fps (frame-per-second) display. Therefore, a compilation could cause tens of frames to be missed, and drop the fps from 60 to 6. This is compilation jank. After the compilation is complete, the animation should be smooth.

To fix this we can precompile shaders either via automated widget tests or just manually running the app to collect the shaders before the release. Then the generated shader files can be bundled into the final build. The size increase is relatively small while the performance gains can be amazing, especially if your app relies on animations a lot. The major problem with this approach is that it needs to be redone for every new build.

Summary

Similarly to my previous more optimistic post, this list could go on much longer. I don’t want to undermine Flutter in any way, but at the same time I feel like we shouldn’t avoid speaking about some obvious problems we encounter daily. Flutter is a wonderful piece of tech, it’s no longer in its infancy. It’s a production-grade ecosystem that many companies and individuals use to build world-class experiences. It’s just a pity there are still some fundamental issues that seem to never go away…


Announcing my newsletter

To make it easier to never miss a new blog post, I decided to start a simple newsletter. It's called Occasional Flutter and I invite you to subscribe today!

Updated: