
Halo Habr! Saya MiloΕ‘ dari Badoo, dan ini adalah pos Habr pertama saya, awalnya diterbitkan di
blog teknologi kami. Semoga Anda menyukainya, dan silakan bagikan dan berkomentar jika Anda memiliki pertanyaan
Jadi ... Bereaksi, amirite ???
Itu muncul di pertengahan dekade (diganggu oleh perang kerangka kerja JavaScript tak berujung), merangkul
DOM , mengejutkan semua orang dengan mencampur HTML dengan JavaScript dan mengubah lanskap pengembangan web yang tak bisa dikenali.
Semua prestasi itu,
bahkan tanpa
menjadi kerangka kerja .
Suka atau benci itu, React melakukan satu pekerjaan dengan sangat baik, dan itu adalah templating HTML. Bersama dengan komunitas yang hebat dan ekosistem yang sehat, tidak sulit untuk melihat mengapa itu menjadi salah satu perpustakaan JavaScript yang paling populer dan berpengaruh, jika bukan yang paling populer.
Di sini, di tim Web Seluler, kami tidak mengikuti kerangka kerja JS yang ketat - atau paling tidak, kerangka kerja yang populer - dan kami menggunakan campuran teknologi warisan dan modern. Meskipun itu bekerja dengan baik bagi kami, memanipulasi DOM biasanya sulit, dan kami ingin mengatasinya dengan mengurangi jumlah pembaruan "manual", meningkatkan penggunaan kembali kode kami dan mengurangi kekhawatiran tentang kebocoran memori.
Setelah beberapa penyelidikan, React dianggap sebagai pilihan terbaik dan kami memutuskan untuk menggunakannya.
Saya bergabung dengan Badoo di tengah proses ini. Setelah bootstrap dan bekerja pada proyek React sebelumnya, saya menyadari pro dan kontra dalam prakteknya, tetapi memigrasi aplikasi yang matang dengan
ratusan juta pengguna adalah tantangan yang sama sekali berbeda.
Jsx
Bereaksi campuran HTML dengan JavaScript dalam format bernama
JSX . Meskipun terlihat seperti bahasa templat, JSX sebenarnya hanya sebuah sintaks, atau
gula sintaksis jika Anda mau, untuk panggilan Bereaksi, sangat mirip dengan HTML.
File HTML kami sendiri terorganisasi dengan baik, dan sebagian besar rendering kami dilakukan hanya dengan
template.render()
. Bagaimana kita bisa mempertahankan tatanan dan kesederhanaan ini saat pindah ke React? Bagi saya, selain kesulitan teknis, satu ide sudah jelas: ganti panggilan yang ada dengan kode JSX.
Setelah beberapa perencanaan awal saya mencobanya dan membungkus alat baris perintah yang melakukan dua hal sederhana:
- Baca template yang dirujuk dalam file UI (JavaScript)
- Ganti panggilan
template.render()
dengan konten HTML
Tentu saja, ini hanya akan membuat kita setengah jalan, karena kita masih harus memodifikasi kode HTML secara manual. Mempertimbangkan volume dan jumlah templat kami, saya tahu bahwa pendekatan terbaik adalah sesuatu yang otomatis. Gagasan orisinil terdengar cukup sederhana - dan jika dapat dijelaskan, dapat diterapkan.
Setelah memperagakan alat awal untuk rekan tim, umpan balik terbaik yang saya dapatkan adalah ada
parser yang tersedia untuk bahasa templating yang kami gunakan. Itu berarti bahwa kita dapat mengurai dan menerjemahkan kode lebih mudah daripada yang kita bisa dengan
ekspresi reguler , misalnya. Saat itulah saya benar-benar tahu bahwa ini akan berhasil!
Lihatlah, setelah beberapa hari, sebuah alat dilahirkan untuk mengonversi
templat HTML seperti
Dust.js menjadi kode Bereaksi JSX. Kami menggunakan Dust, tetapi dengan ketersediaan parser yang luas, prosesnya harus sama untuk menerjemahkan bahasa templating populer lainnya.
Untuk detail lebih lanjut, lewati bagian Open-source di bawah ini. Kami menggunakan alat seperti
Esprima untuk mengurai kode JS, dan generator pengurai
PEG.js untuk mengurai templat Debu. Dalam istilah yang paling sederhana, ini tentang menerjemahkan jenis kode templat ini:
<div class="encounters {?isExpanded}is-expanded{/isExpanded}"> {?showTooltip} <div class="tooltip"> <span>{#_t}{encounters_tooltip}{/_t}</span> <div class="icon"> {@Icon name="icon-encounters" size="stretch" /} </div> </div> {/showTooltip} <div class="images"> {#images} <img src="{src}"> <input type="radio" id="{id}" {?selected}checked{/selected} /> <label for="showme-{id}"> {name} </label> {/images} </div> <div class="footer"> {! encounters-footer template will be injected here !} </div> </div>
untuk setara dengan kode JSX-nya:
<div className="encounters {props.isExpanded ? 'is-expanded' : ''}"> {props.showTooltip ? <div className="tooltip"> <span>{i18n.get('encounters_tooltip')}</span> <div className="icon"> <Icon name="icon-encounters" size="stretch" /> </div> </div> : null} <div className="images"> {props.images.map(item => <img src={item.src}> <input type="radio" id={`showme-${item.id}`} defaultChecked={item.selected ? true : undefined} /> <label htmlFor={`showme-${item.id}`}> {item.name} </label> )} </div> <div className="footer"> {/* encounters-footer template will be injected here */} </div> </div>
Lihat perbandingan berdampingan di
sini .
Setelah ini, proses kami cukup mudah. Kami secara otomatis mengonversi templat kami dari satu format ke format lainnya, dan semuanya berfungsi seperti yang diharapkan (terima kasih, pengujian otomatis). Untuk memulainya, kami mempertahankan API
template.render()
lama kami untuk menjaga agar perubahan tetap terisolasi.
Tentu saja, dengan pendekatan ini Anda masih berakhir dengan template dan tidak "layak" komponen Bereaksi. Manfaat sebenarnya adalah bahwa jauh lebih mudah, jika tidak sepele, untuk beralih ke Bereaksi dari templat yang sudah JSX, dalam kebanyakan kasus hanya dengan membungkus kode templat dalam panggilan fungsi.
Anda mungkin berpikir: mengapa tidak menulis templat baru dari awal? Jawaban singkatnya adalah tidak ada yang salah dengan templat lama kami - kami hanya punya banyak templat. Adapun menulis ulang mereka dan bekerja menuju komponenisasi sejati, itu
cerita yang berbeda .

Beberapa mungkin berpendapat bahwa
model komponen hanyalah tren lain yang mungkin berlalu, jadi mengapa berkomitmen untuk itu? Sulit untuk diprediksi, tetapi satu jawaban yang mungkin adalah
Anda tidak perlu . Jika Anda mengulang dengan cepat, Anda dapat mencoba opsi yang berbeda, tanpa menghabiskan terlalu banyak waktu pada salah satu dari mereka, sampai Anda menemukan format yang paling cocok untuk tim Anda. Itulah salah satu konsep inti bagi kami di Badoo.
Dengan munculnya ES7 / 8 / Next, Elm dan Reason, belum lagi TypeScript dan solusi serupa, kode yang dulunya
*.js
. Alih-alih kewalahan olehnya, mengapa tidak menggunakannya untuk keuntungan kita?
Sumber terbuka
Dengan semangat
melakukan satu hal dengan baik , kami telah membangun alat internal ini dalam beberapa bagian:
- dust2jsx - paket yang bertanggung jawab atas terjemahan debu ke jsx yang sebenarnya
- ratt (React All The Things) - alat baris perintah untuk membaca / menulis file pada disk. Bertanggung jawab untuk menyertakan template yang direferensikan, dan menggunakan
dust2jsx
internal untuk mengubah kode
Kami bahkan telah open-source alat-alat ini - pastikan untuk memeriksanya, serta bahan-bahan sumber terbuka lainnya di halaman
GitHub kami. Silakan berkontribusi atau tinggalkan komentar kami jika Anda menemukan mereka berguna.