Customizing web app initialization
You can customize how a Flutter app is initialized on the web
using the _flutter.loader
JavaScript API provided by flutter.js
.
This API can be used to display a loading indicator in CSS,
prevent the app from loading based on a condition,
or wait until the user presses a button before showing the app.
The initialization process is split into the following stages:
- Loading the entrypoint script
- Fetches the
main.dart.js
script and initializes the service worker. - Initializing the Flutter engine
- Initializes Flutter’s web engine by downloading required resources such as assets, fonts, and CanvasKit.
- Running the app
- Prepares the DOM for your Flutter app and runs it.
This page shows how to customize the behavior at each stage of the initialization process.
Getting started
By default, the index.html
file
generated by the flutter create
command
contains a script tag
that calls loadEntrypoint
from the flutter.js
file:
<html>
<head>
<!-- ... -->
<script src="flutter.js" defer></script>
</head>
<body>
<script>
window.addEventListener('load', function (ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: async function(engineInitializer) {
// Initialize the Flutter engine
let appRunner = await engineInitializer.initializeEngine();
// Run the app
await appRunner.runApp();
}
});
});
</script>
</body>
</html>
The loadEntrypoint
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.
The onEntrypointLoaded
callback receives an engine initializer object as
its only parameter. Use the engine initializer to set the run-time
configuration, and start the Flutter Web engine.
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.
Customizing web app initialization
In this section, learn how to customize each stage of your app’s initialization.
Loading the entrypoint
The loadEntrypoint
method accepts these parameters:
Name | Description | JS Type |
---|---|---|
entrypointUrl |
The URL of your Flutter app’s entrypoint. Defaults to "main.dart.js" . |
String |
onEntrypointLoaded |
The function called when the engine is ready to be initialized. Receives an engineInitializer object as its only parameter. |
Function |
serviceWorker |
The configuration for the flutter_service_worker.js loader. (If not set, the service worker won’t be used.) |
Object |
The serviceWorker
JavaScript object accepts the following properties:
Name | Description | JS Type |
---|---|---|
serviceWorkerUrl |
The URL of the Service Worker JS file. The serviceWorkerVersion is appended to the URL. Defaults to "flutter_service_worker.js?v="
|
String |
serviceWorkerVersion |
Pass the serviceWorkerVersion variable set by the build process in your index.html file. |
String |
timeoutMillis |
The timeout value for the service worker load. Defaults to 4000 . |
Number |
Initializing the engine
As of Flutter 3.7.0, you can use the initializeEngine
method to
configure several run-time options of the Flutter web engine through a
plain JavaScript object.
You can add any of the following optional parameters:
Name | Description | Dart Type |
---|---|---|
assetBase |
The 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 may need this when you embed Flutter web into another app, or when you deploy its assets to a CDN. |
String |
canvasKitBaseUrl |
The base URL from where canvaskit.wasm is downloaded. |
String |
canvasKitVariant |
The 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 |
canvasKitForceCpuOnly |
When true , forces CPU-only rendering in CanvasKit (the engine won’t use WebGL). |
bool |
canvasKitMaximumSurfaces |
The maximum number of overlay surfaces that the CanvasKit renderer can use. | double |
debugShowSemanticNodes |
If true , Flutter visibly renders the semantics tree onscreen (for debugging). |
bool |
hostElement |
HTML Element into which Flutter renders the app. When not set, Flutter web takes over the whole page. | HtmlElement |
renderer |
Specifies the web renderer for the current Flutter application, either "canvaskit" or "html" . |
String |
Engine configuration example
The initializeEngine
method lets you pass any of the configuration
parameters described above to your Flutter app.
Consider the following example.
Your Flutter app should target an HTML element with id="flutter_app"
and
use the canvaskit
renderer. The resulting JavaScript code would resemble
the following:
onEntrypointLoaded: async function(engineInitializer) {
let appRunner = await engineInitializer.initializeEngine({
hostElement: document.querySelector("#flutter_app"),
renderer: "canvaskit"
});
appRunner.runApp();
}
For a more detailed explanation of each parameter, take a look at the
“Runtime parameters” documentation section of the configuration.dart
file of the web engine.
Skipping this step
Instead of calling initializeEngine()
on the engine initializer (and then
runApp()
on the application runner), you can call autoStart()
to
initialize the engine with its default configuration, and then start the app
immediately after the initialization is complete:
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: async function(engineInitializer) {
await engineInitializer.autoStart();
}
});
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:
<html>
<head>
<!-- ... -->
<script src="flutter.js" defer></script>
</head>
<body>
<div id="loading"></div>
<script>
window.addEventListener('load', function(ev) {
var loading = document.querySelector('#loading');
loading.textContent = "Loading entrypoint...";
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: async function(engineInitializer) {
loading.textContent = "Initializing engine...";
let appRunner = await engineInitializer.initializeEngine();
loading.textContent = "Running app...";
await appRunner.runApp();
}
});
});
</script>
</body>
</html>
For a more practical example using CSS animations, see the initialization code for the Flutter Gallery.
Upgrading an older project
If your project was created in Flutter 2.10 or earlier,
you can create a new index.html
file
with the latest initialization template by running
flutter create
as follows.
First, remove the files from your /web
directory.
Then, from your project directory, run the following:
$ flutter create . --platforms=web