Speed Up Flutter Web Startup: Split main.dart.js with Deferred Components

This article explains how to reduce Flutter Web startup time by splitting the bulky main.dart.js file using deferred components, configuring CanvasKit assets via CDN, and optimizing font loading, complete with step‑by‑step code examples and performance measurements.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Speed Up Flutter Web Startup: Split main.dart.js with Deferred Components

Overview

Flutter Web bundles all Dart code into a single main.dart.js, causing large initial download and slow cold start. This guide shows three optimizations for Flutter SDK 3.19.0:

Split the JavaScript bundle using deferred components.

Serve CanvasKit ( canvaskit.js and canvaskit.wasm) from a custom CDN.

Host Google‑fonts locally and update references in the compiled bundle.

1. Splitting the JavaScript bundle

Deferred components are now supported on Web. Add the deferred-components entry under flutter: in pubspec.yaml:

flutter:
  deferred-components:

Import the widget you want to load lazily with the deferred keyword:

import './widget/me_read_achievement_widget.dart' deferred as achievement;

Trigger loading in initState and keep the Future:

late Future<void> _libraryFuture;

@override
void initState() {
  super.initState();
  _libraryFuture = achievement.loadLibrary();
}

Display the widget once the library is loaded using FutureBuilder:

@override
Widget build(BuildContext context) {
  return FutureBuilder<void>(
    future: _libraryFuture,
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.done) {
        return achievement.MeReadAchievementWidget();
      }
      return const CircularProgressIndicator();
    },
  );
}

Build the web app ( flutter build web). The output directory now contains two files: main.dart.js – loaded on initial page load. main.dart.js_1.part.js – fetched only when the deferred widget is requested.

2. Loading CanvasKit from a custom CDN

CanvasKit is required for the Skia‑based renderer and consists of canvaskit.js and canvaskit.wasm. By default they are downloaded from Google’s servers, which adds latency. You can point the engine to a CDN in two ways.

2.1 Engine‑initialisation script

_flutter.loader.loadEntrypoint({
  onEntrypointLoaded: async function(engineInitializer) {
    const appRunner = await engineInitializer.initializeEngine({
      canvasKitBaseUrl: 'https://cdn.example.com/canvaskit/'
    });
    await appRunner.runApp();
  }
});

2.2 Build‑time flag

flutter build web -t lib/main_test.dart \
  --no-tree-shake-icons \
  --dart-define=FLUTTER_WEB_CANVASKIT_URL=https://cdn.example.com/canvaskit/ \
  --release

Replace https://cdn.example.com/canvaskit/ with the base URL where both canvaskit.js and canvaskit.wasm are hosted.

3. Font loading optimization

When CanvasKit is used, Flutter Web also downloads a large set of Noto fonts from fonts.gstatic.com. To avoid this network round‑trip, download the required .ttf files, host them on your CDN, and rewrite the URLs in main.dart.js.

3.1 Identify font URLs

Search the compiled main.dart.js for strings ending with .ttf. Example entry:

"KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf"

3.2 Bulk download script (Python 3)

# coding=utf-8
import os, requests

# Replace this with the portion of main.dart.js that contains the font list
original_text = '...'

font_list = [f for f in original_text.split('"') if f.endswith('.ttf')]
host = 'https://fonts.gstatic.com/s/'
fonts_dir = 'fonts/'

for font_path in font_list:
    url = host + font_path
    resp = requests.get(url)
    local_path = os.path.join(fonts_dir, font_path)
    os.makedirs(os.path.dirname(local_path), exist_ok=True)
    with open(local_path, 'wb') as f:
        f.write(resp.content)

Upload the fonts/ directory to your CDN and replace each original URL in main.dart.js with the corresponding CDN URL.

3.3 Development shortcut

During local development you can avoid CanvasKit and font downloads entirely by using the HTML renderer:

flutter run -d Chrome -t lib/main_test.dart --web-renderer html

4. Measured impact

Applying the three techniques reduced the cold‑start time from roughly 2–3 seconds to a few hundred milliseconds in the author’s tests, saving about 5–6 seconds overall.

Conclusion

By splitting the JavaScript bundle with deferred components, serving CanvasKit assets from a nearby CDN, and hosting required fonts locally, Flutter Web applications built with SDK 3.19.0 achieve significantly faster initial loads, especially for feature‑rich apps that use many widgets and custom fonts.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

FlutterPerformanceWebCDNCode SplittingDeferred ComponentsFont Optimization
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.