Flutter web app initialization

This page details the initialization process for Flutter web apps and how it can be customized.

Bootstrapping

#

The flutter build web command produces a script called flutter_bootstrap.js in the build output directory (build/web). This file contains the JavaScript code needed to initialize and run your Flutter app. You can use this script by placing an async-script tag for it in your index.html file in the web subdirectory of your Flutter app:

html
<html>
  <body>
    <script src="flutter_bootstrap.js" async></script>
  </body>
</html>

Alternatively, you can inline the entire contents of the flutter_bootstrap.js file by inserting the template token {{flutter_bootstrap_js}} in your index.html file:

html
<html>
  <body>
    <script>
      {{flutter_bootstrap_js}}
    </script>
  </body>
</html>

The {{flutter_bootstrap_js}} token is replaced with the contents of the flutter_bootstrap.js file when the index.html file is copied to the output directory (build/web) during the build step.

Customize initialization

#

By default, flutter build web generates a flutter_bootstrap.js file that does a simple initialization of your Flutter app. However, in some scenarios, you might have a reason to customize this initialization process, such as:

  • Setting a custom Flutter configuration for your app.
  • Changing the settings for the Flutter service worker.
  • Writing custom JavaScript code to run at different stages of the startup process.

To write your own custom bootstrapping logic instead of using the default script produced by the build step, you can place a flutter_bootstrap.js file in the web subdirectory of your project, which is copied over and used instead of the default script produced by the build. This file is also templated, and you can insert several special tokens that the build step substitutes at build time when copying the flutter_bootstrap.js file to the output directory. The following table lists the tokens that the build step will substitute in either the flutter_bootstrap.js or index.html files:

TokenReplaced with
{{flutter_js}}The JavaScript code that makes the FlutterLoader object available in the _flutter.loader global variable. (See the _flutter.loader.load() API section below for more details.)
{{flutter_build_config}}A JavaScript statement that sets metadata produced by the build process which gives the FlutterLoader information needed to properly bootstrap your application.
{{flutter_service_worker_version}}A unique number representing the build version of the service worker, which can be passed as part of the service worker configuration (see the "Service Worker Settings" table below).
{{flutter_bootstrap_js}}As mentioned above, this inlines the contents of the flutter_bootstrap.js file directly into the index.html file. Note that this token can only be used in the index.html and not the flutter_bootstrap.js file itself.

Write a custom bootstrap script

#

Any custom flutter_bootstrap.js script needs to have three components in order to successfully start your Flutter app:

  • A {{flutter_js}} token, to make _flutter.loader available.
  • A {{flutter_build_config}} token, which provides information about the build to the FlutterLoader needed to start your app.
  • A call to _flutter.loader.load(), which actually starts the app.

The most basic flutter_bootstrap.js file would look something like this:

js
{{flutter_js}}
{{flutter_build_config}}

_flutter.loader.load();

Customize the Flutter Loader

#

The _flutter.loader.load() JavaScript API can be invoked with optional arguments to customize initialization behavior:

NameDescriptionJS type
configThe Flutter configuration of your app.Object
onEntrypointLoadedThe function called when the engine is ready to be initialized. Receives an engineInitializer object as its only parameter.Function

The config argument is an object that can have the following optional fields:

NameDescriptionDart type
assetBaseThe base URL of the assets directory of the app. Add this when Flutter loads from a different domain or subdirectory than the actual web app. You might need this when you embed Flutter web into another app, or when you deploy its assets to a CDN.String
canvasKitBaseUrlThe base URL from where canvaskit.wasm is downloaded.String
canvasKitVariantThe CanvasKit variant to download. Your options cover:

1. auto: Downloads the optimal variant for the browser. The option defaults to this value.
2. full: Downloads the full variant of CanvasKit that works in all browsers.
3. chromium: Downloads a smaller variant of CanvasKit that uses Chromium compatible APIs. Warning: Don't use the chromium option unless you plan on only using Chromium-based browsers.
String
canvasKitForceCpuOnlyWhen true, forces CPU-only rendering in CanvasKit (the engine won't use WebGL).bool
canvasKitMaximumSurfacesThe maximum number of overlay surfaces that the CanvasKit renderer can use.double
debugShowSemanticNodesIf true, Flutter visibly renders the semantics tree onscreen (for debugging).bool
entryPointBaseUrlThe base URL of your Flutter app's entrypoint. Defaults to "/".String
hostElementHTML Element into which Flutter renders the app. When not set, Flutter web takes over the whole page.HtmlElement
rendererSpecifies the web renderer for the current Flutter application, either "canvaskit" or "skwasm".String

Example: Customizing Flutter configuration based on URL query parameters

#

The following example shows a custom flutter_bootstrap.js that allows the user to select a renderer by providing a renderer query parameter, e.g. ?renderer=skwasm, in the URL of their website:

js
{{flutter_js}}
{{flutter_build_config}}

const searchParams = new URLSearchParams(window.location.search);
const renderer = searchParams.get('renderer');
const userConfig = renderer ? {'renderer': renderer} : {};
_flutter.loader.load({
  config: userConfig,
});

This script evaluates the URLSearchParams of the page to determine whether the user passed a renderer query parameter and then changes the user configuration of the Flutter app. It also passes the service worker settings to use the flutter service worker, along with the service worker version.

The onEntrypointLoaded callback

#

You can also pass an onEntrypointLoaded callback into the load API in order to perform custom logic at different parts of the initialization process. The initialization process is split into the following stages:

Loading the entrypoint script
The load function calls the onEntrypointLoaded callback once the Service Worker is initialized, and the main.dart.js entrypoint has been downloaded and run by the browser. Flutter also calls onEntrypointLoaded on every hot restart during development.
Initializing the Flutter engine
The onEntrypointLoaded callback receives an engine initializer object as its only parameter. Use the engine initializer initializeEngine() function to set the run-time configuration, like multiViewEnabled: true, and start the Flutter web engine.
Running the app
The initializeEngine() function returns a Promise that resolves with an app runner object. The app runner has a single method, runApp(), that runs the Flutter app.
Adding views to (or removing views from) an app
The runApp() method returns a flutter app object. In multi-view mode, the addView and removeView methods can be used to manage app views from the host app. To learn more, check out Embedded mode.

Example: Display a progress indicator

#

To give the user of your application feedback during the initialization process, use the hooks provided for each stage to update the DOM:

js
{{flutter_js}}
{{flutter_build_config}}

const loading = document.createElement('div');
document.body.appendChild(loading);
loading.textContent = "Loading Entrypoint...";
_flutter.loader.load({
  onEntrypointLoaded: async function(engineInitializer) {
    loading.textContent = "Initializing engine...";
    const appRunner = await engineInitializer.initializeEngine();

    loading.textContent = "Running app...";
    await appRunner.runApp();
  }
});