Paling sering, ketika memilih bahasa ini, diharapkan bahwa pengembangan satu aplikasi untuk dua platform akan memakan waktu setengah dari pengembangan dua aplikasi. Tetapi pada akhirnya ternyata pengembangan itu mengambil banyak, jika tidak lebih, karena kesulitan yang tersembunyi di bawah kecemerlangan dan pemasaran luar. Kami akan berbicara tentang beberapa kesulitan serupa yang kami temui dalam beberapa bulan terakhir bekerja dengan React Native.
React Native mengadaptasi Javascript untuk pengembangan seluler. Ini dicapai oleh fakta bahwa ia menggunakan beberapa kolektor untuk membangun proyek - Metro Bundler, yang menginterpretasikan kode JS dan mewakili sumber daya dan pengumpul sistem target. Dalam kasus kami, itu adalah gradle untuk Android. Secara teori, aplikasi React Native harus dimulai dengan cukup sederhana. Perintah run-android run-native memungkinkan Metro Bundler dan membangun aplikasi untuk semua perangkat dan emulator Android yang terhubung.
Pada kenyataannya, ternyata bahkan pada tahap ini ada kesulitan. Kesalahan "Tidak dapat mengunduh bundel JS" terus-menerus muncul di proyek kami, yang berarti bundler tidak dapat menerjemahkan kode ke kode asli. Ternyata kemudian, karena fakta bahwa itu tidak dimulai. StackOverflow mengkonfirmasi dugaan dan menyarankan Anda harus menjalankan bundler di utas terpisah menggunakan perintah mulai asli-reaksi. Ini memungkinkan Anda untuk me-restart bundler hanya jika package.json telah berubah, karena prosedurnya tidak terlalu memperlambat pengembangan.
Package.json adalah file yang berisi satu set modul eksternal untuk aplikasi. Di npmjs.com ada sejumlah besar perpustakaan yang berbeda untuk React Native, memperluas fungsionalitas dan menyederhanakan pengembangan. Banyak perpustakaan (misalnya, Firebase) menggunakan fungsi asli, dan karenanya harus dikaitkan langsung dengan kode asli. Untuk melakukan ini, gunakan perintah <library-name> tautan reaksi asli, yang harus mengonfigurasi hubungan ini dengan kode asli.
Karena fakta bahwa semua perpustakaan ditulis pada waktu yang berbeda, mereka menggunakan versi SDK yang berbeda dan memerlukan pendekatan yang berbeda. Kadang-kadang terjadi bahwa perpustakaan tidak kompatibel satu sama lain, atau versi terbaru dari perpustakaan adalah eksperimental, dan pengembang sendiri menyarankan untuk menurunkan versi ke yang kedua dari belakang. Cukup sering, tautan tidak mengkonfigurasi semua dependensi yang diperlukan. Jadi, untuk firebase yang disebutkan di atas, Anda perlu menambahkan banyak pustaka tambahan dalam kode asli, menghubungkan berbagai repositori eksternal, memodifikasi mainApplication.java (dan ini hanya untuk android!). Untuk Firebase, ada instruksi yang cukup dimengerti untuk melakukan tindakan ini, tetapi untuk perpustakaan lain tidak selalu ada.
Setelah koneksi dengan kode asli dikonfigurasikan, Anda dapat membangun proyek dengan harapan bahwa pustaka yang terhubung akan berfungsi. Ketika berkumpul, perlu diingat bahwa jika Anda mendapatkan kesalahan, maka Anda harus memastikan bahwa itu muncul justru karena tindakan Anda, dan bukan karena kesalahan kolektor. Untuk kepercayaan penuh, Anda harus melakukan urutan tindakan berikut:
rmdir node_modules /s /q && npm cache clean - force && npm i
Perintah ini akan menghapus folder node_modules dan kemudian memuatnya kembali. Ini adalah salah satu tugas terpanjang, oleh karena itu sangat jarang menggunakannya. Pada beberapa proyek, node_modules dapat menempati hingga beberapa gigabytes pada hard drive, dan karenanya penginstalan ulang akan memakan waktu.
rmdir android/app/build /s /q
Selama pengembangan, diketahui bahwa build yang sering gagal adalah konsekuensi dari fakta bahwa kolektor tidak dapat membuat (atau menghapus) folder dari direktori debug. Tindakan ini menyelesaikan masalah yang bereaksi tidak dapat menghapus folder sendiri. Tetapi pada saat yang sama, menghasilkan file untuk folder ini dari awal lagi akan membutuhkan waktu ekstra.
react-native start-reset-cache
Luncurkan Metro Bundler. Tab ini harus tetap terbuka selama proses debugging. Jika kesalahan terjadi, log kesalahan dapat muncul di sini. Kemungkinan besar, jika terjadi kesalahan, proses ini akan berakhir, dan itu harus dimulai lagi.
react-native run-android
Instal aplikasi pada perangkat atau emulator yang terhubung. Sebagian besar kesalahan build terjadi di sini, dan beberapa di antaranya dapat dimengerti, tetapi beberapa sangat tidak rasional dan "disembuhkan" dengan memulai kembali seluruh proses.
Bayangkan proses pembuatan dengan urutan perintah untuk satu proyek (sudah memiliki ranah, redux, navigasi reaksi, sekitar sepuluh perpustakaan lagi) setelah menghubungkan Firebase.
react-native start react-native run-android >> debug react-native run-android >> , metro bundler react-native start react-native run-android >> debug react-native run-android >> ! metro bundler , JS- react-native start >> restart -
Tak perlu dikatakan, itu membutuhkan waktu yang sangat lama? Dan ini bukan proses satu kali: pada saat dijelaskan, prosedur ini diperlukan setelah hampir setiap perubahan dalam kode program. Dengan setiap perpustakaan baru, proyek menjadi semakin tidak stabil, dan proses ini dapat berubah, paling sering menjadi lebih buruk. Debugging aplikasi adalah salah satu fungsi terpenting bagi pengembang, dan dalam hal ini kecepatannya menurun cukup banyak.
Berbicara tentang debugging. React Native debugger tidak hanya memiliki masalah dengan peluncuran. Koreksi kesalahan yang ditemukan sebagai hasil dari tes ini juga merupakan proses yang agak menyakitkan. Dalam reaksi asli, kode JS diterjemahkan ke dalam kode asli, tetapi dikaburkan selama terjemahan. Jadi, jika Anda tidak ingin melihat kesalahan seperti "pengecualian pointer nol di zzz.yyy ()", maka Anda perlu menggunakan debugger bawaan, Anda tidak bisa membaca pengecualian di logcat. Pada kesalahan, debugger menampilkan "layar kematian" merah dengan deskripsinya, sedikit banyak mendorong ke arah koreksi. Tetapi ada masalah dengan bagian ini.
Nah, ketika kesalahannya terlihat seperti ini:

Sangat jelas apa yang terjadi di sini - alih-alih objek array yang diharapkan, this.state.noteArray.map tidak terdefinisi dalam variabel, yang menyebabkan TypeError terkenal. Anda bisa memperbaikinya dengan membuka app.js: 14 dan memeriksa nilai dalam variabel ini sebelum digunakan.
Lebih buruk ketika kesalahannya terlihat seperti ini:

Jadi:

Atau lebih:

Gambar diambil dari Internet, tetapi kami melihatnya langsung. Dan terlepas dari kenyataan bahwa mereka ditampilkan dalam runtime, kesalahan ini bukan karena fakta bahwa ada sesuatu yang salah dalam kode Anda. Ini mungkin disebabkan oleh fakta bahwa Anda menginstal pustaka secara tidak benar, atau jika impor Anda memiliki dependensi yang tidak kompatibel, atau ada yang salah dalam kode asli, dan Bereaksi mencoba untuk menangkap kesalahan. Setiap kesalahan bersifat individual dan diselesaikan dengan sangat berbeda. Bagus bahwa ada StackOverflow dan setidaknya beberapa jenis mode debugging.
Lebih buruk lagi, ketika kesalahan tidak direproduksi dalam debug. Kami mengalami situasi ini ketika mencoba membangun aplikasi dengan React versi baru dengan dukungan arsitektur x64 untuk Android. Saat memasang aplikasi dengan debugger, semuanya berfungsi dengan baik. Tapi begitu kami membuat tester di telepon, semuanya berhenti berfungsi dan rusak begitu berinteraksi dengan basis data. Untuk men-debug non-debugging dengan tergesa-gesa, kami menggunakan pesan konsol, yang dalam hal ini adalah komponen roti panggang Android. Komponen ini menampilkan teks pendek untuk mencapai baris kode tertentu. Secara metodis, lebih disukai membagi kode menjadi dua, kami melokalkan fungsi di mana kesalahan terjadi dan menemukan bahwa metode Object.assign ({}, item) tidak berfungsi dalam versi baru Bereaksi. Beruntung Anda bisa mengganti fungsi ini dengan {... item} yang lebih pendek sambil mempertahankan fungsionalitas aplikasi, tetapi pencarian untuk kesalahan ini menghabiskan waktu sekitar selusin jam kerja.
Setelah penelitian kecil dilakukan mencari alasan. Ternyata, React Native menggunakan mesin Javascript yang berbeda untuk menafsirkan kode JS dalam versi debug dan produksi: untuk debugging mesin Chrome JS, dan di JavaScriptCore. Ya, React Native tidak menerjemahkan JavaScript ke dalam kode asli, tetapi menafsirkannya saat berjalan. Pada saat yang sama, mesin debugging bekerja jauh lebih stabil, dan karena itu bug semakin menyusup ke dalam produksi. Misalnya, artikel ini menunjukkan cara kerja format tanggal dalam kondisi yang berbeda. Kembali ke kesalahan: ternyata setelah memperbarui versi React Native, mesin web produksi produksi kehilangan dukungan untuk Object.assign (). Tetapi mesin debugging tetap sama.
Mungkin opsi terburuk adalah kasus ketika aplikasi rusak di tempat acak, hanya dalam versi produksi dan tanpa log dari Bereaksi Asli. Contoh: setelah menginstal versi rilis aplikasi di telepon, ia "bekerja untuk sementara", dan kemudian "mati tanpa kesalahan atau peringatan pada saat yang acak." Selain itu, kesalahan tidak direproduksi di semua perangkat. Pada akhirnya, dengan coba-coba (dan dengan mendeteksi bahwa Firebase Crashlytics yang disebutkan di atas tidak mengirimkan kesalahan yang sesuai), kami berhasil menangkap log musim gugur yang terlihat seperti ini:

Teks ini bahkan tidak berlaku untuk aplikasi kita, bahkan tidak ditandai dengan warna merah. Tetapi setelah kami mendapatkannya dan pergi ke forum, kami menemukan bahwa versi baru React Native rusak. Dan yang sebelumnya rusak. Pada Pelacak Masalah resmi, kesalahan "Android crash: signal 11 (SIGSEGV)" ada selama dua bulan, dan kami beruntung dua hari sebelum kami pergi ke sana (!) Solusi eksperimental diusulkan untuk memperbaiki kesalahan tersebut.
Sungguh ironis bahwa beberapa pengembang yang harus berurusan dengan Android Studio bingung bahwa IDE memiliki opsi seperti build / clean project atau file / cache tidak valid. Ini diperlukan untuk menghilangkan perilaku gradle yang abnormal, dari pesan kesalahan dan peringatan yang salah, dari kesalahan sinkronisasi. Pengembang bertanya: "mengapa kita harus melakukan pekerjaan untuk IDE kita, dalam situasi seperti itu, perintah ini harus dijalankan secara otomatis." Dan mereka dapat dipahami, tetapi pada saat yang sama, IDE modern melakukan semua pekerjaan sulit di belakang layar. Dan pengembang ini sama sekali tidak bekerja dengan Bereaksi Asli.
Semua hal di atas adalah kasus terisolasi yang telah terjadi selama beberapa minggu terakhir. Di sini kami tidak menjelaskan kompleksitas menjalankan aplikasi dengan Expo, dengan mengatur gaya kode di babel / eslint, kami tidak memarahi Javascript untuk fleksibilitas yang berlebihan, kami tidak memberi tahu bagaimana debugging karena hubungan redux / realm hampir sepenuhnya hilang pada salah satu proyek. Mempertimbangkan kesulitan yang dijelaskan dari dukungan dan pengembangan dan fakta bahwa untuk dua sistem semuanya dikalikan dua, ada baiknya mempertimbangkan apakah React Native benar-benar menguntungkan? Setelah kami menyelesaikan proyek ketiga kami dalam bahasa ini, kami memutuskan tidak. Apa yang kamu pikirkan