Flutter Embedding

Embedding a Flutter web app in a Jaspr website.


To embed a Flutter app into your existing Jaspr website, you need the following setup:

  • Add flutter from the currently installed SDK and jaspr_flutter_embed as dependencies:

    shell
    dart pub add "flutter@{sdk: flutter}" jaspr_flutter_embed

    Optional: You may also add flutter_lints and flutter_test to your dev dependencies:

    shell
    dart pub add "dev:flutter_lints" "dev:flutter_test@{sdk: flutter}"
  • Set the jaspr.flutter option in your pubspec.yaml to embedded:

    yaml
    jaspr:
      flutter: embedded
  • Optional: If your Flutter App uses Material Design, you may set flutter.uses-material-design in pubspec.yaml to true:

    yaml
    flutter:
      uses-material-design: true
  • Create the file web/flutter_bootstrap.js with the following content:

    js
    {{flutter_js}}
    {{flutter_build_config}}

    And include it as a script in your page:

    dart
    // In server or static mode
    Document(
      head: [
        script(src: "flutter_bootstrap.js", async: true),
      ]
    ),
    
    // Or in client mode, add to index.html:
    // <script src="flutter_bootstrap.js" async></script>
  • Add the FlutterEmbedView component to your jaspr app like this:

    dart
    import 'package:jaspr_flutter_embed/jaspr_flutter_embed.dart';
    
    // Import your Flutter app widget, but only on web.
    @Import.onWeb('my_flutter_app.dart', show: [#MyFlutterApp])
    import '<current_filename>.imports.dart';
    
    // This can be any Jaspr component
    class JasprApp extends StatelessComponent {
      JasprApp({super.key});
    
      Component build(BuildContext context) {
        // This is a normal Jaspr component.
        return FlutterEmbedView(
          // We need to set constraints as the flutter view cannot dynamically size itself.
          constraints: ViewConstraints(
              minWidth: 300,
              minHeight: 100,
              maxWidth: double.infinity,
              maxHeight: double.infinity,
          ),
          // Provide an optional loader component that will be displayed while the Flutter app loads.
          loader: MyCustomLoader(),
          // Provide your Flutter app widget.
          widget: kIsWeb ? MyFlutterApp(
            // Provide any widget properties or callbacks.
            // You can pass and share state between Jaspr and Flutter without needing js interop.
            title: 'My Embedded Flutter App',
          ) : null,
        );
      }
    }

    The .imports.dart file is automatically generated by jaspr serve or jaspr build. You may also generate it manually with dart run build_runner build.

  • Finally, run your jaspr app as normal using jaspr serve or jaspr build.

See the documentation of FlutterEmbedView for a description of all available properties.

New projects can be setup with Flutter embedding using jaspr create.

Deferred loading

The jaspr_flutter_embed package itself uses deferred imports internally to optimize the loading of the Flutter framework. To make optimal use of lazy loading the Flutter framework, you should use the FlutterEmbedView.deferred() constructor.

With this the Flutter framework will automatically be lazy-loaded when rendering a FlutterEmbedView for the first time.

As a further optimization, it is also possible to preload the Flutter framework by calling FlutterEmbedView.preload().

Import handling

Any code and components that use the Flutter SDK can only be imported on the client, not the server. That means that when you use server-side rendering, you cannot directly import the above component into your app, or you will get a compilation error.

Instead, you need to use Darts conditional imports to only import the affected code on the client. See @Import.