※ 公式フォーラムで回答したやつの日本語版です
Expo v34でExpo WebのBeta版がアナウンスされました。
Alpha版はちょっと辛い感じでしたが、Betaにもなれば少しは実用性が出てきたかなと思って、デプロイパイプラインを構築してみました。
webpackのデフォルト挙動をケアできてない問題がある
CIサーバー内でデプロイ用にビルドをしてみたところ、次のエラーが発生しました。
$ expo build:web
- Making sure project is set up correctly...
[====================] 100% (24.1 seconds)
Treating warnings as errors because process.env.CI = true.
Most CI servers set it automatically.
Failed to compile.
asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
./fonts/MaterialCommunityIcons.ttf (503 KiB)
webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
webpack勢の皆さまならピンと来たと思うのですが、これはwebpackの performance.maxAssetSize
を超えた場合に起きるエラーです。デフォルトで 250000
バイト以上の静的ファイルのホスティングはパフォーマンス上の問題をもたらすのでやめなさい、という設定ですね。
デバッグ中はwarning扱いなので問題ないのですが、CIサーバーで CI=true
の環境変数が付与されると、warningでもビルドが落ちるようになります。500KB超えの MaterialCommunityIcons.ttf
を明示的に排除する手段が今のところない以上、デフォルト設定のままCIに載せると必ず落ちる、みたいな状況です。
webpackで解決する
さて、このまま手詰まりかと思われたのですが、最近出てきた expo-cli
のv3系で expo customize:web
というコマンドが登場していました(現行の3.0.10
では動かないので注意が必要。後述)。
もともと隠蔽度が高めのExpo Webですが、多くの場合でカスタマイズしたくなる設定ファイルを少しだけ露出させてくれるようです。これでwebpack.config.jsが作れます。
大事なことなのでもう一度言います。 webpack.config.jsが作れます!!!
やったぞ! これで俺たちの勝ちだ!!!!!!(誇張表現)
webpack.config.jsでmaxAssetSizeを変更する
expo customize:web
コマンドで生成したwebpack.config.jsを次のように編集します。
const createExpoWebpackConfigAsync = require('@expo/webpack-config');
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
// Customize the config before returning it.
+
+ config.performance = {
+ ...config.performance,
+ maxAssetSize: 550000,
+ };
+
return config;
};
雑に550000バイトまではOKにしました。
これで実行し直すと、次のようになります。
$ CI=true expo build:web
- Making sure project is set up correctly...
[====================] 100% (23.5 seconds)
Compiled successfully.
上手いこと成果物が作られました。これでデプロイできそうです。
まあ、500KBのフォントファイルなんかダウンロードしたくないので、デプロイはしたもののアプリ内で使わないように気をつけなきゃなあという気持ちですね……(使わない分にはブラウザがロードすることもない)
ビルドをwebpack筋でなんとかできた
今回は雑に maxAssetSize
を編集しましたが、やりようによっては MaterialCommunityIcons.ttf
をwebpackが収集しないようにするような設定もできそうです。createFontLoaderに介入するとよさそう。
Expo Webの方針として、隠蔽がキツいまま、痒いところに手が届かない方針で行くのかなと思っていましたが、開発者側でwebpack.config.jsを弄っていいということであれば、それなりにカスタマイズが効きそうです。Create React Appでいうreact-app-rewiredと近い感覚ですね。
趣味プロダクトみたいなところから、順次導入を試してみたいと思い始めました。
まとめ
今回は調べてませんが、browserslistやhomepageみたいな設定もできると、かなりCreate React App(with rewired)の使い勝手に肉薄していく気がします。
おまけ:expo customize:webがうまく動かない場合のワークアラウンド
expo-cliの v3.0.10
では、 expo customize:web
コマンドがうまく動きません。
$ expo customize:web
Cannot read property 'readConfigJsonAsync' of undefined
TypeError: Cannot read property 'readConfigJsonAsync' of undefined
at action (/expo-cli@3.0.10/src/commands/customize.ts:126:3)
at Command.action (/expo-cli@3.0.10/src/exp.ts:82:13)
どうやらimportの仕方をミスっていたようで、すでに修正がmasterにマージされています。
v3.0.11
か v3.1.0
で修正されると思いますが、それまでの間使えるワークアラウンドがあります。 customize:web
でwebpack.config.jsを選んだときに起こることを、手動で実施します。
-
@expo/webpack-config
をインストールする - ↓のwebpack.config.jsをトップレベルに配置する
const createExpoWebpackConfigAsync = require('@expo/webpack-config');
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
// Customize the config before returning it.
return config;
};
これで expo customize:web
が動かなくても大丈夫です。