Hi! 自動化大好きおじさんデス!
最近Flutterでwebゲームアプリ開発して遊んでいるのですがassetsのファイルを書き換えた際の待ち時間が、メンドクセェ_:(´ཀ`」 ∠):_
dartファイルは更新したらホットリロードされるのにassets下はbuildしないと更新されません。Releaseの時は思わぬ事故を防げるのでいいのですが、Debugでこれだと開発が大変です。
解決方法として、assets
下の更新されたファイルをbuild/flutter_assets/assets
下にコピーする、という手段があります。
> xcopy assets\\* build\\flutter_assets\\assets /d /s /y /f
最初はこれをバッチファイル化して運用しようとしてたのですが、メンドクセェ_:(´ཀ`」 ∠):_
ファイル更新の度にいちいちバッチファイル叩きたくないでござる、ゼッタイに叩きたくないでござる!
Node.jsで開発しているとこの辺だいたい自動化されているので、裏山……いやNode使えばいいのか🤔
nodemon自体は単体で動くプログラムなのでnpmが入ってる環境ならpackage.json書いてしまえば動きます。ただnodemonそのまま設定を書くのはメンドクサイので今回はnpm-watchを使ってみました。
インストール
npmのプロジェクトじゃないのでグローバルに入れてしまいます
> npm install -g npm-watch
設定ファイルの記述
プロジェクトフォルダ直下にpackage.jsonを置きました
{
"watch":{
"assets_data": {
"patterns": ["assets/data"],
"extensions": "*"
}
},
"scripts": {
"assets_data": "xcopy assets\\data\\* build\\flutter_assets\\assets\\data /d /s /y /f",
"watch": "chcp 65001 && npm-watch"
}
}
package.jsonの解説
scriptsの中がnpm run
から見えるコマンドになります。起動にnpm run watch
としてscriptsの中のwatchに設定されたコマンドを実行します。
xcopyがコンソールのキャラセット(デフォルトcp932)でメッセージを出しちゃうので、chcp 65001
を付けておくとnpmさんが期待するutf8でメッセージを出すようになります。その後続けて先ほどインストールしたnpm-watchコマンドが実行されます。
npm-watchコマンドはjsonのwatchの中をパラメータとして認識します。この中に実行したいscriptsのエントリ名(scriptsの中のassets_dataに書かれたコマンドを実行したいのでassets_data)のエントリを作成します。
最低限patterns(ウォッチ対象とするディレクトリ名。サブディレクトリも見てくれる)とextensions(ウォッチ対象とするファイルの拡張子を指定。全て対象なら*)があればいいです。
これで
- npm run watchでscripts中のwatchの行が実行される
- scriptsの上にあるwatchのパラメータでnpm-watchがウォッチ開始
- 更新を検知したらscriptsのassets_dataの行を実行
となり、自動でファイルが更新されます。
xcopyなの? robocopyは使わないの?
robocopyはプロセスが起動したまま先に実行し終わっちゃってnodemonがええのんか?ってエラーを出す(問題はないようですが)ので、xcopyを使うようにしました_(:3」∠)_
実行
package.jsonを置いた場所で実行します。というより実行する場所にpackage.jsonをおきましょう、と
> npm run watch
ファイルを更新してみる
自動で更新されたら成功です
[assets_data] [nodemon] restarting due to changes...
[assets_data] [nodemon] starting `npm.cmd run --silent assets_data`
[assets_data] C:\tmp\FlutterGame1\assets\data\event.toml -> C:\tmp\FlutterGame1\build\flutter_assets\assets\data\event.toml
[assets_data] 1 File(s) copied
[assets_data] [nodemon] clean exit - waiting for changes before restart
Flutterでの注意点
ファイルはちゃんと変わるのですが、APIが至る所でキャッシュします。
例えばloadStringの場合は次のようにcache: false
を付けてキャッシュされないようにしないと反映されません。
self.data = TomlDocument.parse(
await rootBundle.loadString("assets/data/event.toml", cache: false))
.toMap();
cacheコントロールができないAPIならもうブラウザの更新ボタンしかなく(´・ω:;.:...
それでも、それでもbuildよりは圧倒的に速い!