踊る犬.netブログ (旧)

React Nativeでリリースビルドが起動しない問題の解決法

React Nativeを使ってiOSアプリを開発していて、TestFlightで配信しようとした時に問題にぶち当たった。

起動直後に落ちる

配信されたアプリを起動するとすぐにクラッシュしてしまう。
クラッシュレポートも上がってこないから、何が起こったのか分からない。
まるでProvisioning Profileの有効期限が切れた時のような挙動。
しかし、Code SigningやProvisioning Profileの設定は正しい。
そもそも間違っていればTestFlightで配信できないから。

原因1: ダイナミックなクラス名参照を実装している

以下の情報がヒントになった。

Production Buildでは、jsがminifyされる。
その過程で、クラス名もnとかfみたいな短い名前に変更されてしまう。
だから、Klass.constructor.nameのように参照している箇所は全て正しく動作しなくなる。

この実装方法は間違いなので修正する必要がある。

原因2: main.jsbundle が作成されていない

アーカイブの実行はエラー無く完了したから、コンパイル自体に問題は無いと思っていたが、そうではなかった。
アーカイブされたアプリの中身には、<name>.app 直下に main.jsbundle が作成されていなければならない。
このmain.jsbundleが、React Nativeのアプリ本体だ。
しかし何らかの理由でこのファイルがうまく作成されていなかった。

手動でコンパイルしてみる

react-native bundle というコマンドでXcodeを通さずに本番用のビルドが出来る。
以下の通り実行してみると予想通りエラーを得た。ちゃんとXcode上でもレポートしてくれよ・・

$ react-native bundle --entry-file index.ios.js  --bundle-output build/out.js --assets-dest build/ --platform ios --dev false
[3/3/2017, 8:09:03 PM] <start> Initializing Packager
[3/3/2017, 8:09:03 PM] </start><start> Building in-memory fs for JavaScript
[3/3/2017, 8:09:03 PM] <end>   Building in-memory fs for JavaScript (251ms)
[3/3/2017, 8:09:03 PM] <start> Building Haste Map
[3/3/2017, 8:09:04 PM] <end>   Building Haste Map (932ms)
[3/3/2017, 8:09:04 PM] </end><end>   Initializing Packager (1284ms)
[3/3/2017, 8:09:04 PM] <start> Transforming files

Unable to resolve module stream from /<path -to-app>/node_modules/pouchdb-quick-search/dist/pouchdb.quick-search.js: Module does not exist in the module map or in these directories:
  /</path><path -to-app>/node_modules/pouchdb-quick-search/node_modules
,  /</path><path -to-app>/node_modules

This might be related to https://github.com/facebook/react-native/issues/4968
To resolve try the following:
  1. Clear watchman watches: `watchman watch-del-all`.
  2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.
  3. Reset packager cache: `rm -fr $TMPDIR/react-*` or `npm start -- --reset-cache`.

オーケー、どうやらpouchdb-quick-searchが悪さをしているようだ。
エラーメッセージよ、出来れば該当行番号も教えてくれ!!

pouchdb-quick-search の修正

これはアプリ固有の原因なので参考までにして頂きたい。
まずご存知の通りReact Nativeにはstreamというモジュールは存在しない。それはnode.jsの標準モジュールだ。
こいつをrequireしようとしているからbundleでコケているという訳だ。
だからその箇所を修正すればいい。

node_modules/pouchdb-quick-search/dist/pouchdb.quick-search.js:

23605 var Stream;
23606 (function () {
23607   try {
23608     Stream = require('st' + 'ream');
23609   } catch (_) {} finally {
23610     if (!Stream) Stream = require(86).EventEmitter;
23611   }
23612 })();

この require('st' + 'ream') という箇所が原因だった。なんだよ 'st' + 'ream' って。
grepしてもヒットしねぇわけだ!!

以上。

[amazonjs asin=”B01NBIIL2K” locale=”JP” title=”React Native Tutorial: How to Start with React Native. Beginners Guide Book (English Edition)”]