Flutter web support hits the stable milestone
Publish to web and mobile from the same codebase
Our vision for Flutter is to be a portable UI framework for building beautiful app experiences on any platform. Today, as part of Flutter 2, we’re announcing that Flutter’s web support has hit the stable milestone.
The first Flutter release supported iOS and Android, and has been used to bring over 150,000 apps to mobile app stores. Now, adding web support means that those same apps can reach an even broader audience, as well as opening up new ways to build interactive experiences on the web.
In this initial release of web support, we’re focusing on three app scenarios:
- Progressive web apps (PWAs) that combine the web’s reach with the capabilities of a desktop app.
- Single page apps (SPAs) that load once and transmit data to and from internet services.
- Expanding existing Flutter mobile apps to the web, enabling shared code for both experiences.
This article describes what we’ve built so far, and explores examples of how you can take advantage of Flutter’s web support in your own apps.
Our journey to the web
Today’s web platform is richer than ever, with hardware-accelerated 2D and 3D graphics, offline and installation support, and access to the underlying operating system and hardware. The web has allowed a broad array of frameworks that build on this underlying platform to offer developers great flexibility in how they create apps for the web.
Our approach is to build a consistent toolkit that works across all platforms (rather than have two separate frameworks that have subtle deviations of behavior), to ensure that your own code runs without surprises.
At an architectural level, Flutter is a multilayer system with:
- A framework that provides abstractions for common idioms like widgets, animation, and gestures.
- An engine that renders to the target device using the system APIs it exposes.
The framework itself is written in Dart, and the roughly 700,000 lines of core Flutter framework code are the same across all platforms: mobile, desktop, and now web. The same is true for your code; we use either the Dart development compiler (
dartdevc) or the Dart deployment compiler (
Our goal for Flutter is to offer a new way to target the web platform, build on existing foundations, and provide new insights that improve the web for everyone.
Delivering a production-quality stable release
Since our beta release of web support a year ago, we’ve learned a lot about how early adopters are using it, and we’ve worked with a few customers who have now shipped their Flutter web apps to production.
Over this period, we have made major architectural improvements and added features that extend and optimize Flutter for the web, focusing on four areas: performance, web-specific features, desktop form factors, and plugins.
The biggest area of improvement since our early releases is performance. During development, we’ve gained a better understanding of the performance and correctness characteristics of the various rendering technologies available on the web.
We originally started with an HTML, DOM-based model. In this model, Flutter’s web engine translates each generated Flutter scene into HTML, CSS, or Canvas, and renders a frame onto the page as a tree of HTML elements. Even though the HTML renderer offered the greatest compatibility with a wide variety of browsers and had a smaller code size, the HTML renderer’s repaint performance was less suitable for more graphic-intensive applications like Rive, a collaborative tool built with Flutter to create motion graphics.
To handle the fidelity required to render intensive graphics efficiently, we started experimenting with CanvasKit, which enables rendering Skia paint commands in the browser using WebAssembly and WebGL. We discovered that CanvasKit can deliver superior performance, fidelity, and correctness, enabling the level of graphical horsepower expressed in this demo by Felix Blaschke, a talented member of the Flutter community.
Each renderer offers advantages in different scenarios, so Flutter is supporting both rendering modes:
- HTML renderer: Uses a combination of HTML elements, CSS, Canvas elements, and SVG elements. This renderer has a smaller download size.
- CanvasKit renderer: This renderer is fully consistent with Flutter mobile and desktop, has faster performance with higher widget density, but adds about 2MB in download size.
To optimize your Flutter web app for the characteristics of each device, the rendering mode is set by default to auto. This means that your app runs with the HTML renderer on mobile browsers and with CanvasKit on desktop browsers.
You can also use
--web-renderer html or
--web-renderer canvaskit to explicitly choose which renderer your app uses. For more information, see Web renderers.
A Flutter app running in the browser should feel like a web app. So we added features to Flutter that help you use the best of the web.
The web has many strengths, especially its global reach. One of the many reasons to bring your existing Flutter app to the web is to reach users outside of app stores. To do that, we added support for custom URL strategies, to ensure that it’s possible for your users to reach your app anywhere with just a click of a URL. With this feature, you have control over the URLs shown in the address bar as well as the routing of your app on the web.
Hyperlinks are also critical to how users navigate the web. A new
link widget in the
url_launcher package enables users to deep link to anchors within your app or to external websites. You can use
link on relevant widgets, including buttons, inline text, images, and specify whether the link opens in the same tab or in a new tab.
Another integral part of any app is text rendering. Developing a layout system for text was one of the biggest challenges to support Flutter on the web. Since the web lacks a direct-text layout API, Flutter must perform various measurements on the
paragraph by triggering a
layout(). These measurements can become quite expensive, so a new canvas-based text measurement adds supports for both plain and rich text. Now, Flutter can do detailed measurements efficiently on the web, enabling things like painting highlight boxes accurately on selected text.
Interacting with text is just as important as being able to render text quickly and accurately. Text can now be selected, copied, and pasted by using
EditableText widgets. Also, form text fields support autofill by enabling the browser to store data and handle cases for future autofills.
Flutter 2 is particularly suitable for implementing Progressive Web Apps, or PWAs. PWAs are a good fit for bridging the gap between mobile and web apps in a safe and trusted manner through the efforts of Chrome’s Project Fugu.
When you create a Flutter web app, we include a PWA web manifest file, as well as code to setup service workers. The manifest file provides metadata about how your app should run, including information like icons and an app title. Service workers enable caching of resources and running your app offline. When running a Flutter app in the browser as a PWA, you’ll see the opportunity to install it to your device, whether as a mobile or desktop app.
Support for desktop form factors
We want to make Flutter web experiences feel right, regardless of the shape and size of your browser window. On mobile browsers, Flutter apps already have excellent support for gestures and scrolling physics inherited from mobile app support. But desktop browsers offer different UI affordances, and so we’ve updated Flutter accordingly.
For instance, there is an expectation for content on the desktop to display scrollbars that can be controlled by a mouse or keyboard. So the new customizable interactive scrollbars support a theme, a track, and the ability to scroll by dragging a thumb. The
PrimaryScrollController has been expanded so that you can use keyboard shortcuts to scroll without having to wire up your own scroll views.
We also increased the default content density, because mouse pointers support a tighter density than touch devices. And we added a superset of system mouse cursors in the framework to support all platforms.
Finally, to support all users, Flutter’s web semantic features are expanded to support accessibility for Windows, macOS, and ChromeOS. On the web, a second DOM tree called the
SemanticsNode tree is generated in parallel to the
RenderObject DOM tree. The
SemanticsNode tree translates the flags, actions, labels, and other semantic properties into ARIA attributes. Now you can use Narrator, VoiceOver, TalkBack, or ChromeVox screen readers to navigate a Flutter web app.
Since the beta release and with help from the community, support for the following plugins was added:
A few years ago, it wouldn’t have been possible to deliver Flutter on the web with an acceptable level of quality and performance. However, the introduction of new web technologies and continued advances in the platform allowed us to harness much more of the potential of the underlying device. With support for the web, Flutter encompasses every device on the internet with a consistent experience across all modern browsers and devices.
Much of this release was defined by the feedback shared by early web adopters, and by issues filed by the community. And for that, we thank you! Going forward, our primary goal is to address your feedback and resolve issues quickly so that you can stay focused on shipping a high-quality, Flutter app across all of your target platforms.
Performance will likely always be an area of investment. Our goal is to reduce code size and increase frames per second (fps). Today, every Flutter web app downloads the engine code that it needs. We’re looking into possibilities to cache some of this logic, reducing startup time and download size. We recently did work in the Flutter Gallery demo app to reduce code size using deferred libraries and plan to share what we learned soon.
We’re also continuing to refine a few areas over the coming months:
- While CanvasKit is stable, there are a couple of edge cases that aren’t covered, such as font fallbacks for special characters or properly supporting Cross-Origin Resource Sharing (CORS) images.
- PWAs currently cache a subset of resources, so our full offline support still requires extra manual steps to work for CanvasKit.
- Text rendering and functionality, like selecting heavily styled text, is still one of the most complex features we will continue to work on.
- Our plugin ecosystem is something we will also continue to invest in so that Google-published packages have greater parity across mobile and web.
Getting started with Flutter on the web
With the portability of Dart, the power of the web platform, and the flexibility of the Flutter framework, you can now build apps for iOS, Android, and the browser from the same codebase.
For those of you who already have an existing Flutter web app, you can now build your app in the stable channel. If you are new to building Flutter web apps, check out flutter.dev/web, our get started codelab, and the Flutter Engage web breakout session. And, as you’re building your web app, be sure to file any issues on GitHub.
We can’t wait to see what you build with Flutter’s new web support!