Slide 1

Slide 1 text

Flutter for Web 2024 FlutterKaigi mini #2 @Ishikawa 1

Slide 2

Slide 2 text

WHOIS 2 株式会社モニクルに所属 - SWE/プロダクトSRE - ウェブシステムの運用開発 Wasmの同人誌を書いてるWasm の人!!!    asuka@a_skua フロントエンドカンファレンス北海道2024 ↓Wasmの話をしてきた

Slide 3

Slide 3 text

フロントエンドカンファレンス北海道に出していたCfP Dartのウェブ周りの話がしたかった↓ 3

Slide 4

Slide 4 text

FlutterというよりはDart寄りの話 4

Slide 5

Slide 5 text

2024年のDart ● Wasmのサポート (Dart 3.3) ○ DartとWebAssembly ● Flutter 3.22 でstableでサポート ○ Support for WebAssembly (Wasm) 5 $ flutter build web --wasm Wasmにビルドできるようになった main.dart.mjsとmain.dart.wasmが出力されている

Slide 6

Slide 6 text

Wasmを使うと2〜3倍ほど パフォーマンスがよくなるらしい 6 やったね

Slide 7

Slide 7 text

実際使えそう? 7

Slide 8

Slide 8 text

● Safariで動かない問題 ● FireFoxで動かない問題 → 今まで通りcanvaskit.wasmで動いている なんだかんだまだ安定していない(1) 8 Support for WebAssembly (Wasm) DartのWasmはWasmGCがランタイムに実装されているこ とが前提としている Safari→WasmGCをまだ実装していない FireFox→実装にバグがあって使えない

Slide 9

Slide 9 text

なんだかんだまだ安定していない(2) ● CrossOriginヘッダーが必要 →GitHub Pagesでmain.dart.wasmは使われない → 今まで通りcanvaskit.wasmで動いている 9 $ dhttpd '--headers=Cross-Origin-Embedder-Policy=credentialless;Cross-Origin-Opener-Policy=same-origin' skwasmを外部から取得して実行するため, サーバーレスポンスにこれらのヘッダーが必要

Slide 10

Slide 10 text

Flutterではできるけど,Dartだと出来ないが結構ありそう ● httpパッケージをそれぞれ実行してみると... 10 import 'package:http/http.dart' as http; final response = await http.get(Uri.parse('https://example.com')); print(response.body); ⭕ Flutter ❌ Dart $ flutter build web --wasm $ dart compile wasm

Slide 11

Slide 11 text

Q. Why ⭕Flutter ❌Dart ? A. Flutterチームが頑張って実装してくれているから (多分) 11 Wasmはそもそも外部との通信が出来ない設計 (Wasm自体がサンドボックスになっている) 外部と通信する部分は 頑張って実装する 必要がある

Slide 12

Slide 12 text

頑張って実装した 12

Slide 13

Slide 13 text

頑張って実装した 13 Wasmから実行できる https://pub.dev/packages/cf_workers final response = await fetch( Request('GET', Uri.parse('https://example.com')).toJS ).toDart; print(response.body);

Slide 14

Slide 14 text

頑張って実装するには ● dart:js_interop ● dart:js_interop_unsafe 現状この2つのライブラリが必要 14 dart:js_interop →JSの型が定義されている →@JSデコレータ dart:js_interop_unsafe →JSの関数呼び出しなどが定義されている

Slide 15

Slide 15 text

dart:js_interop こういう使い方ができる 15 import 'dart:js_interop'; @JS('greet') external JSString greet(JSString name); void main() { print(greet('Dart'.toJS).toDart); } ここの型の扱いに注意が必要 ※ DartとJSの型を直接やり取りできない (globalThis as any).greet = (name: string) => `Hello, ${name}!`; JS側の実装例

Slide 16

Slide 16 text

dart:js_interop_unsafe JSオブジェクトのコンストラクタの呼び出しやメソッド,プロパティへのアクセスを提供. 16 final jsreq = globalContext .getProperty("Request".toJS) .callAsConstructor(“https://example.com”.toJS); final url = jsreq.getProperty("url".toJS).toDart; 少し面倒だけど,DartからJSオブジェクトを操作するための機能が提供されている.

Slide 17

Slide 17 text

Wasmがサポートされて変わったこと 17

Slide 18

Slide 18 text

Wasmがサポートされて変わったこと 18 dat2js ● main.dart.js を出力 dart2wasm ● main.dart.wasm ● main.dart.mjs import "./main.js"; import { compileStreaming } from "./main.dart.mjs"; const app = await compileStreaming( fetch(new URL("./main.dart.wasm", import.meta.url)), ); const instance = await app.instantiate({}); instance.invokeMain(); ESモジュールをサポート

Slide 19

Slide 19 text

まだ変わってないこと グローバルプロパティ にしかアクセスできない. 19 import 'dart:js_interop'; @JS('greet') external JSString greet(JSString name); void main() { print(greet('Dart'.toJS).toDart); } @JSデコレーターは グローバルしか定義できない (globalThis as any).greet = (name: string) => `Hello, ${name}!`; globalThisにマッピングする必要がある

Slide 20

Slide 20 text

まだ変わってないこと グローバルプロパティ にしかアクセスできない. → ESモジュールに対応するなら,スコープをグローバルではなくモジュールに限定した い. 20

Slide 21

Slide 21 text

気になる機能 Wasmはモジュールのimport/exportをサポートしている. Imports and exports (dart-lang/sdk/pkg/dart2wasm) 21 @pragma("wasm:import", "foo.bar") external void fooBar(Object object); const instance = await app.instantiate({ foo: { bar() { }, } }); instance.invokeMain(); Wasmモジュールのimport/exportをDartでもサ ポートしている (※現状はDartの内部向け) 今後この機能が開発者も使えるようになると嬉しい

Slide 22

Slide 22 text

dart2wasmはまだまだ開発中 22 ● daart2wasmがリリースされた直後は@pragmaも使うことができてたが,最新版だ と内部向け機能としてコンパイルエラーになる ● リリース直後と現在の.mjsファイルの中身が結構書き換わっている →この辺りの仕様が安定するまでもう少しかかりそう

Slide 23

Slide 23 text

Flutter for Web 2024 ● Wasmビルドがstableにはなったけど,まだアーリー向けの機能で安定するまでに もう少しかかりそう ● Wasmが使えない場合はcanvaskitが自動的に使われるので,とりあえず--wasm オプションつけておくでもそんなにデメリットない ● Flutter側は実装頑張ってくれているけど,Dartから直接Wasmを使おうとすると ,Wasmの仕様を知らないとハマる罠がそこそこある ○ (著書買ってね❤) ● dart2wasmでESモジュールがサポートされたので,Webとの相性が良さそうなので 今後の発展に期待したい 23