Pular para o conteúdo principal

Compilação WebAssembly (Wasm)

Aprenda a compilar sua aplicação web Dart para WebAssembly.

Você pode compilar aplicações web do Dart e do Flutter para WebAssembly (dart2wasm) como alternativa ao JavaScript em builds de produção.

Suporte a WebAssembly

#

Ao compilar Dart para WebAssembly, tenha em mente os seguintes requisitos e comportamentos da plataforma:

  1. O dart2wasm tem como alvo três propostas padronizadas de WebAssembly: WasmGC (coleta de lixo), JS String Builtins (wasm:js-string) e Exception Handling da Fase 4 (try_table e exnref). Para executar os módulos compilados em um navegador, é necessário pelo menos:

    • Chrome ou Edge 137+
    • Safari 26.2+ (macOS e iOS)
    • Firefox 134+ (ou 147+ para Flutter web)

    Para mais detalhes de compatibilidade entre navegadores, veja a documentação do Flutter Wasm.

  2. Por padrão, a saída Wasm compilada tem como alvo ambientes JavaScript (como navegadores) e gera um arquivo de runtime complementar <name>.mjs. Para compilar um módulo WebAssembly independente para runtimes que não são web, como o Wasmtime 39+ (usando -W gc,exceptions,function-references=y), passe --standalone para o dart compile wasm. Quando --standalone está definido, o dart:js_interop não é permitido.

  3. Apenas o mecanismo de interoperabilidade JS de próxima geração do Dart é suportado ao compilar para Wasm.

  4. A ferramenta webdev não oferece suporte atualmente à compilação Wasm (webdev serve ou webdev build). Em vez disso, siga os passos em Compilando sua aplicação web para Wasm.

Deferred loading

#

Por padrão, as aplicações compiladas não usam deferred loading. O deferred loading em Wasm é experimental. Para habilitá-lo, passe a flag --enable-deferred-loading:

dart compile wasm --enable-deferred-loading ...

Para habilitar o deferred loading, o carregador da sua aplicação precisa fornecer um callback que carregue os bytes dos módulos deferidos:

js
import { compileStreaming } from './main.mjs';
​
const app = await compileStreaming(fetch('main.wasm')); // or compile(...)
const instantiatedApp = await app.instantiate({}, {
  loadDeferredModules: (modules, handleModuleByteSource) => {
    return Promise.all(
      modules.map((m) => fetch(m).then((r) => handleModuleByteSource(m, r)))
    );
  },
});
instantiatedApp.invokeMain();

Imports condicionais e suporte a SIMD

#
  • Imports condicionais (dart.library.isolate): Ao compilar com dart2wasm, dart.library.isolate é avaliado como false nos imports condicionais (if (dart.library.isolate)), igual ao comportamento do dart2js e do ddc.
  • SIMD de 128 bits em Wasm (v128): No dart2wasm, os tipos SIMD de dart:typed_data (Int32x4, Float32x4, Float64x2, Int32x4List, Float32x4List e Float64x2List) são implementados com as instruções SIMD nativas de 128 bits v128 do WebAssembly.

Pacotes suportados

#

Para encontrar pacotes compatíveis com Wasm, use o filtro wasm-ready no pub.dev.

Um pacote é "wasm-ready" se não importa bibliotecas não compatíveis com Wasm, como dart:html ou dart:js. Você encontra a lista completa de bibliotecas não permitidas na página de interoperabilidade JS.

Compilando sua aplicação web para Wasm

#

Use o comando dart compile wasm na CLI dart para invocar o compilador Wasm do Dart e do Flutter:

dart help compile wasm -v
Compile Dart to a WebAssembly/WasmGC module.

Usage: dart compile wasm [arguments] <dart entry point>
-h, --help                              Print this usage information.
-o, --output                            Write the output to <file name>.
                                        This can be an absolute or relative path.
-v, --verbose                           Print debug output during compilation
    --enable-asserts                    Enable assert statements.
-O, --optimization-level=<level>        Controls optimizations that can help reduce
                                        code-size and improve performance of the
                                        generated code.
                                        [0, 1 (default), 2, 3, 4]
    --[no-]minify                       Minify names that are needed at runtime (such
                                        as class names). Affects e.g.
                                        `<obj>.runtimeType.toString()`). If passed,
                                        this takes precedence over the
                                        optimization-level option.
    --[no-]strip-wasm                   Whether to strip the resulting wasm file of
                                        static symbol names.
                                        (defaults to on)
    --[no-]source-maps                  Generate a source map file.
                                        (defaults to on)
    --[no-]enable-deferred-loading      Emit multiple modules based on the Dart
                                        program's deferred import graph.
    --standalone                        Compile to a WebAssembly module without
                                        JavaScript interop. Dart-specific host
                                        imports are necessary to load these modules.
-D, --define=<key=value>                Define an environment declaration. To specify
                                        multiple declarations, use multiple options
                                        or use commas to separate key-value pairs.
                                        For example: dart compile wasm -Da=1,b=2
                                        main.dart

Para compilar e executar uma aplicação web Dart com Wasm, siga estes passos:

  1. Crie uma aplicação web e entre no diretório dela:

    dart create -t web mywebapp
    cd mywebapp
    

    O template cria uma pequena aplicação web usando o package:web, que é necessário para executar Wasm. Certifique-se de que suas aplicações web foram migradas de dart:html para package:web.

  2. Compile a aplicação para Wasm em um diretório de saída site:

    dart compile wasm -O2 web/main.dart -o site/main.wasm
    

    Isso gera site/main.wasm, o runtime JavaScript complementar site/main.mjs e site/main.wasm.map.

  3. Copie os arquivos web estáticos:

    cp web/index.html web/styles.css site/
    
  4. Como o index.html carrega o main.dart.js, crie o site/main.dart.js para importar o runtime site/main.mjs gerado e instanciar o site/main.wasm:

    site/main.dart.js
    js
    (async function () {
      const { compileStreaming } = await import('./main.mjs');
      const app = await compileStreaming(fetch('main.wasm'));
      const instantiatedApp = await app.instantiate({});
      instantiatedApp.invokeMain();
    })();
    
  5. Sirva o diretório site usando o dhttpd:

    dart run dhttpd@ --path site
    

Você também pode testar este pequeno exemplo de sandbox.

Encontrou essa página sem tradução ou que precisa de correção? Abra uma issue e nos ajude a manter esse site em PT-BR para ajudar pessoas como você.