Saltar al contenido principal

Inicialización de aplicaciones web de Flutter

Personaliza cómo se inicializan las aplicaciones de Flutter en la web.

Esta página detalla el proceso de inicialización para las aplicaciones web de Flutter y cómo se puede personalizar.

Bootstrapping

#

El comando flutter build web produce un script llamado flutter_bootstrap.js en el directorio de salida de la compilación (build/web). Este archivo contiene el código JavaScript necesario para inicializar y ejecutar tu aplicación de Flutter. Puedes usar este script colocando una etiqueta de script asíncrono para él en tu archivo index.html en el subdirectorio web de tu aplicación de Flutter:

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

Alternativamente, puedes incrustar en línea todo el contenido de el archivo flutter_bootstrap.js insertando el token de plantilla {{flutter_bootstrap_js}} en tu archivo index.html:

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

El token {{flutter_bootstrap_js}} se reemplaza con el contenido del archivo flutter_bootstrap.js cuando el archivo index.html se copia al directorio de salida (build/web) durante el paso de compilación.

Personalizar la inicialización

#

De forma predeterminada, flutter build web genera un archivo flutter_bootstrap.js que realiza una inicialización simple de tu aplicación de Flutter. Sin embargo, en algunos escenarios, es posible que tengas motivos para personalizar este proceso de inicialización, como:

  • Establecer una configuración personalizada de Flutter para tu aplicación.
  • Cambiar la configuración para el service worker de Flutter.
  • Escribir código JavaScript personalizado para ejecutarse en diferentes etapas del proceso de arranque.

Para escribir tu propia lógica de bootstrapping personalizada en lugar de usar el script predeterminado producido por el paso de compilación, puedes colocar un archivo flutter_bootstrap.js en el subdirectorio web de tu proyecto, el cual se copiará y se usará en lugar de el script predeterminado producido por la compilación. Este archivo también es una plantilla, y puedes insertar varios tokens especiales que el paso de compilación sustituye en el momento de la compilación al copiar el archivo flutter_bootstrap.js al directorio de salida. La siguiente tabla enumera los tokens que el paso de compilación sustituirá en los archivos flutter_bootstrap.js o index.html:

TokenReemplazado con
{{flutter_js}} El código JavaScript que hace que el objeto FlutterLoader esté disponible en la variable global _flutter.loader. (Consulta la sección de la API _flutter.loader.load() a continuación para obtener más detalles).
{{flutter_build_config}} Una sentencia de JavaScript que establece los metadatos producidos por el proceso de compilación, lo que proporciona al FlutterLoader la información necesaria para realizar correctamente el bootstrap de tu aplicación.
{{flutter_service_worker_version}} Un número único que representa la versión de compilación del service worker, que se puede pasar como parte de la configuración del service worker (consulta la información de "Advertencia común" más abajo).
{{flutter_bootstrap_js}} Como se mencionó anteriormente, esto incrusta en línea el contenido del archivo flutter_bootstrap.js directamente en el archivo index.html. Ten en cuenta que este token solo se puede usar en el archivo index.html y no en el propio archivo flutter_bootstrap.js.

Escribir un script de bootstrap personalizado

#

Cualquier script flutter_bootstrap.js personalizado debe tener tres componentes para iniciar con éxito tu aplicación Flutter:

  • Un token {{flutter_js}}, para hacer que _flutter.loader esté disponible.
  • Un token {{flutter_build_config}}, que proporciona información sobre la compilación al FlutterLoader necesaria para iniciar tu aplicación.
  • Una llamada a _flutter.loader.load(), que realmente inicia la aplicación.

El archivo flutter_bootstrap.js más básico se vería algo así:

js
{{flutter_js}}
{{flutter_build_config}}

_flutter.loader.load();

Personalizar el cargador de Flutter

#

La API de JavaScript _flutter.loader.load() se puede invocar con argumentos opcionales para personalizar el comportamiento de inicialización:

NombreDescripciónJS type
config La configuración de Flutter de tu aplicación. Object
onEntrypointLoaded La función a la que se llama cuando el motor está listo para ser inicializado. Recibe un objeto engineInitializer como su único parámetro. Function

El argumento config es un objeto que puede tener los siguientes campos opcionales:

NombreDescripciónDart type
assetBase La URL base del directorio de assets de la aplicación. Añade esto cuando Flutter se cargue desde un dominio o subdirectorio diferente al de la aplicación web real. Es posible que necesites esto cuando incrustes Flutter web en otra aplicación, o cuando despliegues sus recursos en una CDN. String
canvasKitBaseUrl La URL base desde donde se descarga canvaskit.wasm. String
canvasKitVariant La variante de CanvasKit a descargar. Tus opciones incluyen:

1. auto : Descarga la variante óptima para el navegador. La opción tiene por defecto este valor.
2. full : Descarga la variante completa de CanvasKit que funciona en todos los navegadores.
3. chromium : Descarga una variante más pequeña de CanvasKit que utiliza APIs compatibles con Chromium. Advertencia : No uses la opción chromium a menos que planees usar únicamente navegadores basados en Chromium.
String
canvasKitForceCpuOnly Cuando es true, fuerza el renderizado solo por CPU en CanvasKit (el motor no usará WebGL). bool
canvasKitMaximumSurfaces La cantidad máxima de superficies de superposición (overlay surfaces) que puede usar el renderizador CanvasKit. double
debugShowSemanticNodes Si es true, Flutter renderiza visiblemente el árbol de semántica en pantalla (para depuración). bool
entrypointBaseUrl La URL base del punto de entrada (entrypoint) de tu aplicación Flutter. De forma predeterminada es "/". String
hostElement Elemento HTML en el que Flutter renderiza la aplicación. Cuando no está establecido, Flutter web se apodera de toda la página. HtmlElement
renderer Especifica el renderizador web para la aplicación Flutter actual, ya sea "canvaskit" o "skwasm" . String
forceSingleThreadedSkwasm Fuerza al renderizador Skia WASM a ejecutarse en modo de un solo hilo para mayor compatibilidad. bool

forceSingleThreadedSkwasm

#

Una bandera booleana para forzar al renderizador Skia WebAssembly (skwasm) a ejecutarse en modo de un solo hilo. Esto es útil si:

  • Tu entorno no soporta WASM multi-hilo. Por ejemplo, SharedArrayBuffer no está disponible o faltan las cabeceras de seguridad requeridas.
  • Quieres la máxima compatibilidad de navegador.
  • Usa false (predeterminado) para permitir el renderizado multi-hilo cuando sea compatible, lo que mejora el rendimiento.

Ejemplo de uso

#
js
_flutter.loader.load({
  config: {
    renderer: 'skwasm',
    forceSingleThreadedSkwasm: true,
  },
});

Ejemplo: Personalizar la configuración de Flutter según los parámetros de consulta de la URL

#

El siguiente ejemplo muestra un flutter_bootstrap.js personalizado que permite al usuario seleccionar un renderizador al proporcionar un parámetro de consulta renderer, como ?renderer=skwasm, en la URL de su sitio web:

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,
});

Este script evalúa los URLSearchParams de la página para determinar si el usuario pasó un parámetro de consulta renderer y luego cambia la configuración de usuario de la aplicación Flutter.

El callback onEntrypointLoaded

#

También puedes pasar un callback onEntrypointLoaded a la API load para ejecutar lógica personalizada en diferentes partes del proceso de inicialización. El proceso de inicialización se divide en las siguientes etapas:

Carga del script de punto de entrada

La función load llama al callback onEntrypointLoaded una vez que se inicializa el Service Worker y el punto de entrada main.dart.js ha sido descargado y ejecutado por el navegador. Flutter también llama a onEntrypointLoaded en cada Hot Restart durante el desarrollo.

Inicialización del motor de Flutter

El callback onEntrypointLoaded recibe un objeto inicializador del motor como su único parámetro. Usa la función initializeEngine() del inicializador del motor para establecer la configuración en tiempo de ejecución, como multiViewEnabled: true, y arrancar el motor web de Flutter.

Ejecución de la aplicación

La función initializeEngine() devuelve una Promise que se resuelve con un objeto ejecutor de la aplicación (app runner). El ejecutor de la aplicación tiene un único método, runApp(), que ejecuta la aplicación Flutter.

Agregar vistas a (o eliminar vistas de) una aplicación

El método runApp() devuelve un objeto aplicación Flutter. En el modo multivista, los métodos addView y removeView se pueden usar para gestionar las vistas de la aplicación desde la aplicación host. Para obtener más información, consulta el Modo incrustado.

Ejemplo: Mostrar un indicador de progreso

#

Para dar retroalimentación al usuario de tu aplicación durante el proceso de inicialización, usa los hooks proporcionados para cada etapa para actualizar el 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...";
    // If you have a `config`, pass it here. The config given to `load()`
    // is not forwarded when you supply your own `onEntrypointLoaded`.
    const appRunner = await engineInitializer.initializeEngine();

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

Advertencia común

#

Si experimentas una advertencia similar a la siguiente:

Warning: In index.html:37: Local variable for "serviceWorkerVersion" is deprecated.
Use "" template token instead.

Puedes solucionar esto eliminando la siguiente línea del archivo web/index.html:

web/index.html
html
var serviceWorkerVersion = null;