By Mariam Hasnany, Product Manager, Flutter

Our vision for Flutter is to be a portable UI framework that builds beautiful app experiences across the platform. As part of the Release of Flutter 2, Web support for Flutter has reached a stable release milestone.

The first version of Flutter is available for iOS and Android, and developers have released more than 150,000 apps with Flutter on mobile app stores. Now, with the addition of Web support, these applications can reach a wider audience and open up new ways to build interactive experiences on the Web.

In this initial release of Web support, we focused on three application scenarios:

  • Progressive Web Apps (PWA) combine the high coverage of the Web with the power of desktop applications.
  • Single Page apps (SPA), which can be loaded once and dynamically exchange data with Internet services.
  • Extend the existing Flutter mobile application to the Web, sharing code on both platforms.

This article describes our work to date and shares several examples intended to help developers implement Flutter web support in their applications.

IRobot Education developed the iRobot Coding application with Flutter to provide a programming learning experience to the public through this Web application

Journey to the Web

Today’s Web platform is more diverse than ever, with hardware accelerated 2D and 3D graphics, offline capabilities and installation experiences, and access to underlying operating systems and hardware. A wide variety of frameworks have been built on top of the underlying web platform, so developers have a great deal of flexibility when creating Web applications.

Flutter is written in Dart, which compiles to JavaScript, so the natural next step was to explore the possibility of supporting the Web platform. This is in line with our vision of providing a portable framework that allows you to build beautiful UIs wherever you can draw pixels.

Our approach is to build a consistent toolkit that works across all platforms (rather than building two separate frameworks with various subtle differences) to ensure that developers’ code runs without surprises.

The Flutter framework consists of a series of layers, which include:

  • A framework to provide abstractions for common idioms such as widgets, animations, and gestures
  • Engine that renders on the target device using a public system API

The framework itself is written in Dart. Approximately 700,000 lines of the Flutter framework core code are the same across all platforms: mobile, desktop, and now Web. The same is true for your code, which we compile into JavaScript using the Dart development compiler (DartDevc) or Dart deployment compiler (Dart2JS), which can be hosted on the server.

Since Dart has the ability to compile the Flutter framework (and the developer’s application code) into JavaScript, our support for the web becomes replacing the underlying C++ rendering engine used by mobile applications with code that maps the web platform API. Flutter does not simply port widgets to their HTML equivalents. Flutter’s Web engine provides developers with two renderers: One is an HTML renderer optimized for size and compatibility, and the other is a CanvasKit renderer that uses WebAssembly and WebGL to render browser canvases via Skia draw commands.

Our requirement for Flutter is to provide a new way to develop for the Web platform, to provide new insights on top of existing ones, and to provide a better Web experience for everyone.

Release a stable version available for production

Since the beta version of Web support was released a year ago, we have learned a lot about early adopter usage and have worked with some customers who have now put their own Flutter Web applications into production.

During this time, we have made significant architectural improvements, adding features to extend and optimize Flutter’s Web support. The additions focus on four areas: performance, Web-specific features, desktop hardware adaptation, and plug-ins.

performance

Performance is the most significant improvement since the early release. During development, we gained a deeper understanding of the performance and accuracy characteristics of various rendering technologies on the Web.

Our earliest work was on DOM-based HTML. In this rendering mode, the Web engine of a Flutter converts each generated Flutter scene into HTML, CSS, or Canvas and renders it as a frame on the page as a tree of HTML elements. Although HTML renderers are maximally compatible with browsers and their code size is small, the redraw performance of HTML renderers is not suitable for graphics-intensive applications such as Rive, a collaboration tool for creating dynamic images built with Flutter.

Rive is a tool for creating custom animations. The team has rebuilt the application with the Web version of Flutter and released a beta version

To provide the fidelity needed to render dense graphics efficiently, we began experimenting with CanvasKit, which can be rendered in a browser using The Skia draw command using WebAssembly and WebGL. We have found that the Performance, fidelity and accuracy of the CanvasKit renderer are even better. See the Demo of the Flutter Plasma by Felix Blaschke, a talented German developer in the Flutter community — amazing effects created with CanvasKit.

△ Flutter Plasma is a demo created by Felix Blaschke that runs on Safari, Firefox, Edge and Chrome

Different renderers have their own advantages in different scenarios, so Flutter supports both the following rendering modes:

  • HTML renderer: a combination of HTML elements, CSS, Canvas and SVG. This rendering mode has a smaller download file size.
  • CanvasKit Renderer: Renders exactly the same as Flutter mobile and desktop, with better performance, higher widget density, but increased download file size by about 2MB.

To optimize your Flutter Web application for each device, the render mode is set to automatic by default. This means that your application will run with an HTML renderer on a mobile browser and a CanvasKit renderer on a desktop browser.

You can also use –web-renderer HTML or –web-renderer canvaskit to specify which renderer to use. For more information, please refer to the official documentation.

Web-only features

Flutter applications running in a browser should feel like Web applications. So we’ve added some features to Flutter to help you take advantage of the Web.

The Web has many advantages, not least its global reach. One of the reasons to bring your existing Flutter application to the Web is to reach users outside the app store. To do this, we have added custom URL policies to ensure that your users can access your application from anywhere by clicking on a URL. With this capability, you can control the urls displayed in the address bar and the routing of your application on the Web.

△ The Showroom page for the Flutter Plasma demo is actually an example of a URl_strategy plug-in based on a Flutter custom URL strategy

Hyperlinks are also critical when users navigate the Web. A new link widget in the URl_Launcher package enables users to direct deep links to anchors within your application or to external websites. You can use links on related widgets, including buttons, inline text, images, and specify whether the link opens on the same TAB or in a new TAB.

Text rendering is essential for any application. Developing a text layout system is one of the major challenges in building Flutter Web support. Because the Web lacks a direct text layout API, Flutter must perform various measurement operations on Parapraph by triggering layout(). Sometimes these measurements can be quite expensive, so we added a Canvas based text measurement that supports both plain and rich text. Flutter can now efficiently take fine measurements on the Web to perform correct drawing tasks, such as correctly highlighting selected text.

Interacting with text is just as important as rendering text quickly and accurately. With the SelectableText and EditableText widgets, you can not only select text in the Flutter Web application, but also perform copy-and-paste operations. In addition, form text fields now support auto-filling, and browsers can store data for later filling.

Flutter 2 is particularly suited for progressive Web applications (PWA). We recommend that developers use PWA to bridge the gap between mobile and Web applications in a secure and trusted way through Chrome’s Project Fugu.

Invoice Ninja’s PWA app uses the same code base as their existing Flutter mobile app

When creating the Flutter Web application, we provide the PWA Web manifest file and the code to set up the service worker. The manifest file provides metadata about how the application should behave, including information such as ICONS and application titles. Service Workers can cache resources and run applications offline. When you run Flutter as a PWA in your browser, you can install Flutter as a mobile or desktop application on your device.

Suitable for various desktop devices

Although browsers come in all shapes and sizes, we all want to provide a good Flutter Web experience. Since Flutter was originally designed for mobile applications, the Flutter Web app already provides good support for gesture and scrolling physics in mobile browsers. But the desktop browser UI is rendered and used differently, so we updated Flutter accordingly.

For example, users want the application to display a scroll bar when running in a desktop browser, so they can control it with a mouse or keyboard. We’ve added customizable interactive scrollbars for desktop devices, which means we can use themes for scrollbars, display scrollbar tracks, and drag sliders. We’ve also extended PrimaryScrollController to make it easy for users to scroll with keyboard shortcuts and save you the work of using a custom scroll view.

Property management solution built by Spica Technologies for Zurich Insurance, an excellent example of building applications with Flutter Web for business and desktop device users

In addition, we increased the default content density because the mouse pointer can interact with more content than touch devices. We also added a collection of system mouse cursors for various platforms to the framework.

Finally, to enable Flutter web to support all users, we have extended the web semantics of Flutter to support accessibility on Windows, macOS, and chromeOS. To achieve a frictionless experience on the Web, we generated a similar DOM tree in parallel to the RenderObject DOM tree, called the SemanticsNode tree. The SemanticsNode tree transforms tags, actions, tags, and other semantic attributes into ARIA attributes. You can now use the Flutter Web application via the Anna, VoiceOver, TalkBack or ChromeVox screen reader.

Plugin support for Flutter Web

Finally, we have brought Web support to the most commonly used plug-ins, enabling you to bring your Own Flutter application to the Web platform. With the Flutter plug-in, your code can interoperate with the native development libraries of the platform on which you are running. When you run the Flutter application on the Web, you can access existing JavaScript libraries through plug-ins.

Since the beta release, we have added Web support for the following plug-ins with the help of the community:

  • image_picker
  • google_maps
  • firebase_analytics
  • firebase_storage
  • connectivity
  • cloud_firestore
  • cloud_functions
  • cross_file

Looking to the future

A few years ago, we were not able to provide Flutter with acceptable quality and performance on the Web. However, the advent of new Web technologies and platform advances have allowed us to unleash the potential of underlying devices. With Support for the Web, Flutter was able to encompass every device on the Internet, giving users a consistent experience across all modern browsers and devices.

A significant portion of this release comes from feedback from early Web users and issues submitted by the community, and we would like to thank you again for your contributions! Going forward, our primary goal is to quickly process everyone’s feedback and resolve the issue in a timely manner so that everyone can focus on releasing high-quality Flutter applications on all target platforms.

Performance improvements never end. Our goal was to reduce code volume and improve frame rate performance (FPS). Today, every Flutter Web application only downloads its required engine code. We are investigating the possibility of caching part of the logic to reduce startup time and download file size. We recently tried using delay libraries to reduce code size in the Flutter Gallery demo app and will be sharing our progress soon.

In the coming months, we also intend to continue to refine the following areas:

  • While CanvasKit is stable, some boundary use cases are problematic, such as font fallback for special characters and corresponding support for cross-domain resource sharing (CORS) images.
  • PWA currently caches only a subset of resources, and full offline support still requires additional manual steps to properly adapt to CanvasKit.
  • Text rendering and functionality, such as text selection for more complex styles, are still one of the features we continue to work on.
  • We will also continue to work to improve the plugin ecosystem and make the Package published by Google more uniform across mobile and Web.

Simplebet builds a highly interactive embedded NFL and NBA betting experience within Fanduel’s existing mobile app suite with Flutter Web support

Start using Flutter Web immediately

With the portability of Dart, the power of the Web platform, and the flexibility of the Flutter framework, you can now build applications for iOS, Android, and browsers using the same code base.

If you have developed the Flutter Web application, you can now build it in a stable channel. If you are just learning to build a Flutter Web application, please visit the official documentation for our Introductory Codelab course and the Web talk on Flutter Engage. If you find any problems when building web applications, please feel free to go to GitHub and submit them to us.

We look forward to seeing the wonderful applications you build with Flutter Web!