Frontend Development 12 min read

Performance Optimization and Element‑Embedding for Flutter Web (FFW)

This article analyzes the performance drawbacks of Flutter For Web's two rendering modes, presents practical optimization techniques for both HTML and CanvasKit renderers, introduces the new element‑embedding feature, and proposes a seamless AB‑switching solution to combine fast initial load with smooth interactive performance.

HomeTech
HomeTech
HomeTech
Performance Optimization and Element‑Embedding for Flutter Web (FFW)

Background

In recent years Flutter‑based apps have proliferated because of their flexible development experience, rich ecosystem, and easy maintenance. Flutter code can be slightly adjusted to compile both native apps and Web/H5 sites (Flutter For Web, abbreviated FFW). However, FFW‑generated Web pages often suffer from slow first‑paint and occasional frame‑rate stutters, especially under the two different rendering modes.

1. Rendering Modes and Performance Optimization

1.1 Rendering Mode Overview

HTML rendering mode: uses custom HTML elements, CSS, canvas and SVG; the final HTML contains very few tags and relies heavily on canvas, which limits browser friendliness.

CanvasKit rendering mode: compiles Skia to WebAssembly and renders via WebGL; it requires loading wasm kernels and Noto fonts but offers better performance and compatibility. It is recommended for internal web systems where first‑paint speed is less critical.

1.2 Optimization Experience (HTML Rendering)

► 1.2.1 First‑Paint Speed Optimization

Icon font subsetting (use latest Flutter SDK to automatically trim Material Design fonts).

Enable gzip compression on the server to halve the size of main.dart.js .

Chunk and hash the main JavaScript file; split it into multiple parts and load them in parallel.

Use the flutter_web_optimizer tool:

flutter build web --web-renderer html --release --pwa-strategy none
flutter pub run flutter_web_optimizer optimize --asset-base ./

HTML‑level optimizations: apply defer , preconnect , dns-prefetch , etc.

► 1.2.2 Refresh Frame‑Rate Optimization

Build Refresh Related

Local refresh: limit the rebuild scope using StreamBuilder or Provider for partial updates.

Keep build methods clean; avoid heavy logic inside them to prevent frequent rebuilds.

Prefer stateless or static widgets; use KeepAlive where appropriate to preserve state and reduce rebuilds.

Scroll Component Related

Use SingleChildScrollView with Column for complex, limited‑size lists.

Use ListView.builder for long or uniform lists to recycle items.

Apply custom ScrollPhysics (e.g., spring‑based) to control speed and bounce.

class AhCustomScrollPhysics extends ScrollPhysics {
  const AhCustomScrollPhysics({ScrollPhysics? parent}) : super(parent: parent);

  @override
  AhCustomScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return AhCustomScrollPhysics(parent: buildParent(ancestor));
  }

  @override
  SpringDescription get spring => SpringDescription.withDampingRatio(
        mass: 0.1,   // inertia
        stiffness: double.maxFinite, // end speed
        ratio: 0.1,   // damping
      );
}

1.3 Optimization Experience (CanvasKit Rendering)

► 1.3.1 First‑Paint Speed Optimization

Wasm kernel handling: set the canvasKitBaseUrl prefix to a local CDN to avoid slow Google CDN downloads.

goCanvaskit = () => {
  console.log(target);
  _flutter.loader.loadEntrypoint({
    entrypointUrl: "./flutter_canvaskit/main.dart.js",
    onEntrypointLoaded: async (engineInitializer) => {
      let appRunnerCanvaskit = await engineInitializer.initializeEngine({
        hostElement: target,
        canvasKitBaseUrl: "./flutter_canvaskit/canvaskit/",
      });
      await appRunnerCanvaskit.runApp();
      console.log("canvaskit loaded.");
    }
  });
};

► 1.3.2 Noto Font Handling

Load Noto fonts at startup to prevent missing‑glyph issues.

var fontLoader2 = FontLoader("Noto Sans SC");
fontLoader2.addFont(fetchFont2());
await fontLoader2.load();

Future
fetchFont2() async {
  var url = Uri.parse('http://{your-cdn-host}/ah-assets/...otf');
  final response = await http.get(url);
  if (response.statusCode == 200) {
    return ByteData.view(response.bodyBytes.buffer);
  } else {
    throw Exception('Failed to load font');
  }
}

1.4 First‑Paint Optimization Data

Performance measurements show that HTML mode approaches traditional Vue.js first‑paint times, while CanvasKit delivers frame‑rate comparable to native Flutter apps but still lags in initial load due to wasm and font assets.

2. element‑embedding New Feature

element‑embedding, introduced in Flutter SDK 3.7 and showcased at Flutter Forward 2023, allows Flutter’s rendering output to be embedded as a div canvas layer that can be lazily loaded and communicate with the host (e.g., Angular.js or Vue.js) via JavaScript functions.

Low‑intrusiveness: does not affect host’s first‑paint speed.

Interactivity: host and Flutter code can exchange data through JS functions.

Expands FFW usage scenarios.

3. Replacement AB Scheme

Utilize FFW to produce two rendering artifacts:

HTML renderer for fast first‑paint.

CanvasKit renderer for smooth subsequent interactions.

During user interaction, the hidden CanvasKit element‑embedding is lazily loaded; once ready, state parameters are transferred from the HTML version to the CanvasKit version and a silent switch occurs, preserving scroll position and other UI state, making the transition virtually imperceptible.

3.1 Switching Process

Load HTML rendering artifact as the host.

Embed CanvasKit artifact hidden inside the host.

After each user action, check if CanvasKit has finished rendering.

If ready, pass state, replace the host view, and continue interaction without noticeable delay.

3.2 Application Scenarios

Suitable for pages with moderate interaction complexity where fast initial load and later high‑performance interactivity are both required.

Conclusion

While traditional web frameworks (Vue.js, React.js) remain primary choices for pure web development, Flutter For Web can still be valuable, especially when converting existing Flutter mobile code to Web/H5. The presented optimization and element‑embedding‑based AB‑switching strategy offers a practical path to balance first‑paint speed and interactive performance.

FlutterPerformanceOptimizationwebCanvasKitelement-embeddinghtml-renderer
HomeTech
Written by

HomeTech

HomeTech tech sharing

0 followers
Reader feedback

How this landed with the community

login 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.