Help us understand the problem. What is going on with this article?

Expo Web Betaのsize limit問題から見えた、実用性への道筋

公式フォーラムで回答したやつの日本語版です

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では動かないので注意が必要。後述)。

スクリーンショット_2019-08-26_17_26_50.png

もともと隠蔽度が高めの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と近い感覚ですね。

趣味プロダクトみたいなところから、順次導入を試してみたいと思い始めました。

まとめ

今回は調べてませんが、browserslisthomepageみたいな設定もできると、かなり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.11v3.1.0 で修正されると思いますが、それまでの間使えるワークアラウンドがあります。 customize:web でwebpack.config.jsを選んだときに起こることを、手動で実施します。

  1. @expo/webpack-config をインストールする
  2. ↓のwebpack.config.jsをトップレベルに配置する
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 が動かなくても大丈夫です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away