Flutterアプリを開発している際、まずはWeb(Chrome)を使っているという方も多いのではないでしょうか。個人的には色々な環境で動かしたいので、まずWebで作ってからiOSやAndroid向けの調整を行っています。
そんな中、完全にネットワークがない状況下(飛行機やネットワークが非常に弱いところ)だとアプリが表示されるのに時間がかかったり、エラーが出てしまいます。原因としては下記のエラーです。
canvaskit.js:1 Failed to load resource: net::ERR_NAME_NOT_RESOLVED
これはFlutterのWebアプリがcanvaskit-wasmをUNPKG経由で取得しているのに起因して発生するエラーです。移動中も快適に開発するためには、ネットワーク要素を排除して完全オフラインにするのが肝要です。もちろんUNPKGが運悪く落ちている時に開発が停滞してしまうのも避けられるでしょう。
他にもフォントが絡むので、この2つを解決します。
canvaskit-wasmの解決
基本
まずcanvaskit-wasmのファイルを web/js
フォルダ(新しく作成)以下に配置します。ファイルはUNPKG - canvaskit-wasmからダウンロードできます。
必要なのは以下の4つのファイルです。
- bin/canvaskit.js
- bin/canvaskit-wasm
- bin/profiling/canvaskit.js
- bin/profiling/canvaskit.wasm
このファイルを web/js
フォルダ以下に配置します。
web/js
├── canvaskit.js
├── canvaskit.wasm
└── profiling
├── canvaskit.js
└── canvaskit.wasm
駄目だった方法
ネットで調べてみると、実行時のコマンドライン引数で指定する方法が挙げられています。
flutter run \
-d chrome \
--web-renderer=canvaskit \
--dart-define=FLUTTER_WEB_CANVASKIT_URL=./js/
実際、Flutterのリポジトリにも、そのように書かれています。しかし、これをlaunch.jsonに記述して、VS CodeでFlutterアプリを起動しても有効になりませんでした。
成功した方法
成功した方法は、 web/index.html
を編集する方法です。JavaScriptを以下のように編集します。
<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = null;
// 以下を追加
window.flutterConfiguration = {
canvasKitBaseUrl: "/js/"
};
</script>
これで、canvaskit-wasmがローカル経由で読み込まれるようになります。
フォントの適用
これで終わったかと思ったのですが、ChromeのDev Toolsで見ると、フォントもGoogleのサイト経由でダウンロードされていました。CanvasKitで描画している場合、フォントがないと豆腐だらけになってしまうはずです。
そこで、以下の2つのフォントをダウンロードします。これは利用しているフォントに依りますのでご注意ください。恐らくこの2つのフォントはデフォルトで利用されると思います。
ダウンロード&展開したら、 fonts
フォルダ(新規作成)以下に配置します。
fonts
├── noto_sans
│ ├── NotoSansJP-Black.otf
│ ├── NotoSansJP-Bold.otf
│ ├── NotoSansJP-Light.otf
│ ├── NotoSansJP-Medium.otf
│ ├── NotoSansJP-Regular.otf
│ ├── NotoSansJP-Thin.otf
│ └── OFL.txt
└── roboto
├── LICENSE.txt
├── Roboto-Black.ttf
├── Roboto-BlackItalic.ttf
├── Roboto-Bold.ttf
├── Roboto-BoldItalic.ttf
├── Roboto-Italic.ttf
├── Roboto-Light.ttf
├── Roboto-LightItalic.ttf
├── Roboto-Medium.ttf
├── Roboto-MediumItalic.ttf
├── Roboto-Regular.ttf
├── Roboto-Thin.ttf
└── Roboto-ThinItalic.ttf
そして、 pubspec.yaml に設定を追加します。
flutter:
fonts:
- family: Noto Sans JP
fonts:
- asset: fonts/noto_sans/NotoSansJP-Black.otf
weight: 900
- asset: fonts/noto_sans/NotoSansJP-Bold.otf
weight: 700
- asset: fonts/noto_sans/NotoSansJP-Light.otf
weight: 300
- asset: fonts/noto_sans/NotoSansJP-Medium.otf
weight: 500
- asset: fonts/noto_sans/NotoSansJP-Regular.otf
weight: 400
- asset: fonts/noto_sans/NotoSansJP-Thin.otf
weight: 100
- family: Roboto
fonts:
- asset: fonts/roboto/Roboto-Thin.ttf
weight: 100
- asset: fonts/roboto/Roboto-Light.ttf
weight: 300
- asset: fonts/roboto/Roboto-Regular.ttf
weight: 400
- asset: fonts/roboto/Roboto-Medium.ttf
weight: 500
- asset: fonts/roboto/Roboto-Bold.ttf
weight: 700
- asset: fonts/roboto/Roboto-Black.ttf
weight: 900
最後に、main.dartなりでアプリを立ち上げる際にフォントを指定します。これは中華フォントの異なる漢字が適用されるのも防止できます。
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue, fontFamily: 'Noto Sans JP'),
home: const MyAppPage(),
);
まとめ
これで必要なファイルがlocalhost経由で取得できるようになり、オフラインでも開発が進められるようになります。
ニフクラ mobile backendやHexabaseのようなクラウドサービスをアプリ内で使っている場合には、そこはネットワーク必須になってしまうのですが…UI調整などはオフラインで進められるでしょう。