skip to content

In Flutter on Android, how do deferred components with loadLibrary() reduce the initial download, and what setup do they need?

level: seniorimportance: nice to knowfreq 16%

answer

  1. dynamic feature modules on Android
  2. deferred as plus loadLibrary()
  3. deferred-components in pubspec.yaml
  4. the loading-units YAML file
  5. debug treats them as normal imports

basics

~20 s

Deferred components split Dart code and assets into Android dynamic feature modules that download at runtime when loadLibrary() is called. They need deferred imports, a deferred-components section in pubspec.yaml, Play Store split support and flutter build appbundle.

solid answer

~40 s

On Android, Flutter can compile a library you import with `deferred as` into a separate **loading unit**, package it as a dynamic feature module inside the app bundle, and install it only when code calls `loadLibrary()` on that prefix, so the base download shrinks. Setup: declare components under `flutter: deferred-components:` in `pubspec.yaml` (each with a `name` and `libraries` and optionally `assets`); make the application support split installs, most simply `io.flutter.embedding.android.FlutterPlayStoreSplitApplication`; and build with `flutter build appbundle`, whose validator generates the Android module files and records loading units in `deferred_components_loading_units.yaml`, which you commit. Guard every use behind the `loadLibrary()` future. Limits: you still upload one whole bundle, debug builds treat deferred imports as normal ones, and `DeferredComponent.installDeferredComponent` is for asset-only components.

code

yaml · 5 lines
yaml
flutter:
  deferred-components:
    - name: chartsComponent
      libraries:
        - package:transit_app/charts/charts_screen.dart

go deeper

for a junior

Know that Flutter on Android can download parts of an app later, and that code behind a deferred import needs loadLibrary() first.

for a middle

Describe the setup: pubspec deferred-components, split-install application class, flutter build appbundle and its validator.

for a senior

Judge when splitting is worth it, and design the loading and failure UI plus the release-mode testing it demands.

for a principal

Decide feature boundaries so components map to real user segments, and weigh the build and support cost against download savings.

## The idea Most users never open every screen. If a heavy feature, say a charts dashboard, lives behind one menu item, shipping its code and assets to everyone inflates the install for little benefit. **Deferred components** let a Flutter Android app download that feature **while the app is running**, the first time it is needed. Two mechanisms meet here: - **Dart deferred imports**: `import 'charts_screen.dart' deferred as charts;` tells the compiler that the library is loaded later; `charts.loadLibrary()` returns a `Future<void>` that completes when the code is available. (The language rules for deferred imports are a separate topic.) - **Android dynamic feature modules**: the Flutter tool packages each deferred component as a feature module inside the Android App Bundle, delivered on demand through the Play Store. ## Setup, step by step 1. **Split-install support.** Set the application class in `AndroidManifest.xml` to `io.flutter.embedding.android.FlutterPlayStoreSplitApplication`, which enables split installs and provides the Play Store deferred component manager. Large apps can wire these up manually instead. 2. **Opt in.** Add a `deferred-components:` entry under `flutter:` in `pubspec.yaml`. It may start empty. 3. **Write the deferred library and guard its use.** Import with `deferred as`, call `loadLibrary()` (for example in `initState`) and render the feature only when that future completes, typically through a `FutureBuilder` with a progress indicator. 4. **Build with `flutter build appbundle`.** The validator runs in two phases: before and after `gen_snapshot` produces loading units. It writes recommended files (feature module `build.gradle`, manifests, string resources, the loading-unit mapping) into `build/android_deferred_components_setup_files` for you to review and copy; it never edits `android/` itself. 5. **Assign loading units.** The tool records them in `deferred_components_loading_units.yaml`; commit it so teammates' changes to loading units get caught. Then list each component's `name` and `libraries` (and optional `assets`) in `pubspec.yaml`. ## Rules worth knowing - Every import of the deferred library must be `deferred`, or it cannot be split out. - Listing one library of a loading unit assigns the **whole unit** to that component. - Unassigned loading units stay in the implicit **base** component. - Calling `loadLibrary()` again after it loaded completes quickly, but not synchronously; calling it early pre-loads to hide latency. ## Limits and trade-offs | Limit | Consequence | |---|---| | Android and web only | iOS gets no split; the code ships in the app | | Whole app bundle uploaded each release | no partial updates of a single component | | Debug mode treats deferred imports as regular ones | test real splitting in profile or release | | Download can fail or be slow | every entry point needs loading and error UI | | `--no-deferred-components` | builds everything into one library; `loadLibrary()` then completes on the next event-loop turn | For components that carry only assets, `DeferredComponent.installDeferredComponent(componentName: ...)` downloads them without loading Dart code, and `uninstallDeferredComponent` requests removal. ## When it is worth the complexity Deferred components add build validation, Android module files and failure handling. They pay off for large, rarely used features, for the charts screen in a 60 MB app, not for a 200 KB settings page.

  • Why doesn't a debug run show the charts component being downloaded?
    Flutter only performs deferred loading in profile and release builds on Android; in debug mode all deferred components are treated as regular imports. Test the real download path with a release or profile app bundle installed through a store testing track or a local bundle tool.
  • Why commit deferred_components_loading_units.yaml to source control?
    It records which loading units `gen_snapshot` produced. When another change adds, moves or removes a unit, the validator compares against this file and fails the build with instructions, instead of silently shipping a component layout nobody reviewed.

saying these in an interview costs you the question

  • Deferred components let you ship updates to one module without uploading a new bundle.
  • Deferred components also split the iOS download.
  • Code from a deferred library can be used before loadLibrary() completes.
  • Debug builds are the right place to test the component download.
  • The build tool edits the android directory automatically to add feature modules.