Skip to content

feature: deferred routing #32

Description

@Mastersam07

Motivation

Deferred shell branches shipped in 0.21.0-dev.1 (KaiselBranch.deferred(loadLibrary: feature.loadLibrary)) — a tab's code loads on first activation, with errorBuilder + retry. But deferral is only available at branch granularity. A heavy route on the main stack (an editor, a report viewer, an admin area) still ships in the initial bundle even if most users never open it. On Flutter web that's paid in initial JS download; on Android it blocks using deferred components per feature.

Proposal

First-class per-route deferral with parity to what branches already have:

import 'package:app/editor/editor.dart' deferred as editor;

builder: (context, route) => switch (route) {
  EditorRoute() => KaiselDeferredScreen(
    load: editor.loadLibrary,
    builder: (context) => editor.EditorScreen(),
    // loadingBuilder / errorBuilder with retry, matching KaiselBranch.deferred
  ),
  ...
},

Design questions

  • Deep links & restoration: a URL/restored stack landing directly on a deferred route must trigger the load before first build — the loading state appears inside the route's page, not as a blank app.
  • Transitions: pushing a deferred route ideally delays the page transition until the library resolves (or animates into the loading state — decide which default).
  • Guards: guards run on values, so they need no code from the deferred library — worth stating as a guarantee.
  • loadLibrary caching: Dart already memoizes it; the widget just needs idempotent handling.

Non-goals

Automatic inference of what to defer — the deferred as import stays an explicit app decision, same as branches.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions