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)”]