Published in


Optimizing performance in Flutter web apps with tree shaking and deferred loading

For the best user experience it is important that an app loads fast. The initial load time of a Flutter web application can be improved by minimizing its JavaScript bundle. The Dart compiler includes features such as tree shaking and deferred loading, both of which minimize the JavaScript bundle. This article explains how they work and how you can use them in your application.

Tree shaking by default

When compiling a Flutter web application, the JavaScript bundle is generated by the dart2js compiler. A release build has the highest level of optimization, which includes tree shaking your code.

Tree shaking is the process of eliminating dead code, by only including code that is guaranteed to be executed. This means that you do not need to worry about the size of your app’s included libraries because unused classes or functions are excluded from the compiled JavaScript bundle.

To see tree shaking in action:

  1. Create a Dart file greeter.dart:
abstract class Greeter {
String greet(String name);
class EnglishGreeter implements Greeter {
String greet(String name) => 'Hello $name!';
class SwedishGreeter implements Greeter {
String greet(String name) => 'Hej $name!';
void main() {

2. Run dart2js -O4 greeter.dart in your terminal and take a look at the generated output out.js.

In the generated JavaScript code, there aren’t any references to the SwedishGreeter class, or any inclusion of the string Hej $name, as it was removed during tree shaking by the compiler.

The compiler can only figure out what code is reachable, and what is dead code, with static analysis. Take the following example, where the greeter is defined depending on the system locale:

Locale locale = Localizations.localeOf(context);
if (locale.languageCode == 'sv') {
greeter = SwedishGreeter();
} else {
greeter = EnglishGreeter();

The compiler doesn’t know the user’s system locale, therefore both EnglishGreeter and SwedishGreeter are included in the JavaScript bundle. For such use cases deferred loading can help in minimizing the initial bundle size.

Only load code when needed with deferred loading

Deferred loading, also called lazy loading, allows you to load libraries if and when needed. It can be used to load rarely-used functionality of an application. Please note that deferred loading is a dart2js feature, so this is not available for Flutter mobile applications. In the simplest case, mark an imported package or file as deferred and wait for it to load before using it:

import 'greeter.dart' deferred as greeter;void main() async {
await greeter.loadLibrary();
runApp(App(title: greeter.EnglishGreeter().greet('World')));

Compiling this code generates two JavaScript files. When loadLibrary is called on the deferred import, it loads the greeter library.

In Flutter, where everything is a widget, you might want to make use of the FutureBuilder. A widget’s build method is expected to be synchronous, therefore you can’t call await on loadLibrary inside of a build method. However, you can return a FutureBuilder in a build method, and you can also use it to show a different UI while the library is loading:

import 'greeter.dart' deferred as greeter;FutureBuilder(
future: greeter.loadLibrary(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(greeter.greet('World'));
} else {
return Text('Loading...');

To try it yourself (see a full example on GitHub), open Chrome DevTools and click the Network tab to inspect network activity. Reload the page to see when the library is loaded and imported. In the following screenshot, loading the main.dart.js_1.part.js file is deferred:

Deferred loading of localizations in the Flutter Gallery

The Flutter Gallery supports over 70 languages, but most users only use one. Deferring the loading of the localization strings is a great use of this feature. For example, after implementing deferred loading of localization strings in Flutter Gallery, the app’s initial JavaScript bundle size was cut in half. If you have a lot of localization strings in your Flutter web application, consider deferring the loading of those files. The gen_l10n.dart script includes the flag --use-deferred-loading for this purpose (currently only available on the 1.19 SDK master channel).

This post is a part of a series about what we learned when improving performance for the Flutter Gallery. I hope you found it useful and that you learned something that you can apply to your Flutter web application!

This post is a part of a series about what we learned when improving performance for the Flutter Gallery. Articles in the Creating performant Flutter web apps series:




Flutter is Google's mobile UI framework for crafting high-quality native interfaces on iOS, Android, web, and desktop. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source. Learn more at https://flutter.dev

Recommended from Medium

Building a Ruby on Rails x JavaScript Application from Scratch

O.J. Gillom hey you!!! I added you as editor too and changed it to we so see if you like it!!!

MongoDB + Prisma query optimization (manual indexing)

Why choose Nodejs for Backend Web Development in 2022?

Why choose Nodejs for Backend Web Development in 2022?

JavaScript and It’s use cases in Industries

Important JavaScript Concepts Every Developer MUST Know

Angular New Project Boilerplate: Workspace, Unit testing, Pre-commits hooks ,Custom Library…

HTML Boilerplate

How to Update Node.js Version on Mac?

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Per Classon

Per Classon

Software Engineer 👨🏼‍💻

More from Medium

Show Test Coverage of a Flutter app in Visual Studio Code

Flutter Integration Tests Gain Momentum

Hosting a private Dart package repository

Integrating C library in a desktop Flutter app using Dart FFI