Log pangembang ngarep-mburi Habr: refactoring lan nggambarake

Log pangembang ngarep-mburi Habr: refactoring lan nggambarake

Aku tansah kasengsem ing carane Habr wis kabentuk saka njero, carane workflow wis kabentuk, carane komunikasi wis kabentuk, apa standar digunakake lan carane kode umume ditulis ing kene. Begjanipun, kula pikantuk kalodhangan kados mekaten, amargi kula nembe dados tim habra. Nggunakake conto refactoring cilik saka versi seluler, aku bakal nyoba kanggo njawab pitakonan: apa iku kaya kanggo karya kene ing ngarep. Ing program: Node, Vue, Vuex lan SSR karo saus saka cathetan babagan pengalaman pribadi ing Habr.

Babagan pisanan sing sampeyan kudu ngerti babagan tim pangembangan yaiku ana sawetara saka kita. Ora cukup - iki telung ngarep, loro mburi lan pimpinan teknis kabeh Habr - Baxley. Ana, mesthi, uga tester, desainer, telung Vadim, sapu ajaib, spesialis marketing lan Bumburums liyane. Nanging mung ana enem kontributor langsung kanggo sumber Habr. Iki cukup langka - proyek karo pamirsa multimillion-dollar, kang saka njaba katon kaya perusahaan raksasa, ing kasunyatan katon luwih kaya wiwitan mulyo karo struktur organisasi flattest bisa.

Kaya akeh perusahaan IT liyane, Habr ngakoni ide Agile, praktik CI, lan liya-liyane. Nanging miturut perasaanku, Habr minangka produk berkembang luwih akeh ing gelombang tinimbang terus-terusan. Dadi, kanggo sawetara sprint berturut-turut, kita sregep ngode, ngrancang lan ngrancang maneh, ngrusak lan ndandani, ngrampungake tiket lan nggawe sing anyar, ngethok rake lan nembak awake dhewe, supaya pungkasane ngeculake fitur kasebut menyang produksi. Lan banjur ana jeda tartamtu, periode pembangunan maneh, wektu kanggo nindakake apa sing ana ing kuadran "penting-ora penting".

Iki minangka sprint "off-season" sing bakal dibahas ing ngisor iki. Wektu iki kalebu refactoring versi seluler Habr. Umumé, perusahaan duwe pangarep-arep sing dhuwur, lan ing mangsa ngarep kudu ngganti kabeh zoo inkarnasi Habr lan dadi solusi lintas platform universal. Ing sawijining dina bakal ana tata letak adaptif, PWA, mode offline, kustomisasi pangguna, lan akeh liyane sing menarik.

Ayo nyetel tugas

Sawise, ing stand-up biasa, salah sawijining ngarep ngomong babagan masalah arsitektur komponen komentar versi seluler. Kanthi pikiran iki, kita nganakake rapat mikro kanthi format psikoterapi kelompok. Kabeh padha genti-genti ngendikane sing lara, kabeh dicathet ing kertas, padha simpati, padha ngerti, kajaba ora ana sing keplok. Asil ana dhaptar 20 masalah, kang digawe cetha yen mobile Habr isih dalan dawa lan eri kanggo sukses.

Aku utamané prihatin babagan efisiensi panggunaan sumber daya lan apa sing diarani antarmuka sing lancar. Saben dina, ing rute omah-kerja-omah, aku weruh telpon lawasku banget nyoba nampilake 20 judhul ing feed. Iku katon kaya iki:

Log pangembang ngarep-mburi Habr: refactoring lan nggambarakeAntarmuka Habr seluler sadurunge refactoring

Apa sing kedadeyan ing kene? Ing cendhak, server nyedhiyakake kaca HTML kanggo kabeh wong kanthi cara sing padha, ora preduli manawa pangguna wis mlebu utawa ora. Banjur JS klien dimuat lan njaluk data sing dibutuhake maneh, nanging diatur kanggo wewenang. Yaiku, kita nindakake tugas sing padha kaping pindho. Antarmuka kelip-kelip, lan pangguna ndownload satus ekstra kilobyte sing apik. Ing rinci kabeh katon malah luwih serem.

Log pangembang ngarep-mburi Habr: refactoring lan nggambarakeSkema SSR-CSR lawas. Wewenang mung bisa ditindakake ing tahap C3 lan C4, nalika Node JS ora sibuk ngasilake HTML lan bisa njaluk proxy menyang API.

Arsitèktur kita wektu iku diterangake kanthi akurat dening salah sawijining pangguna Habr:

Versi seluler iku omong kosong. Aku ngomong kaya ngono. A kombinasi elek saka SSR lan CSR.

Kita kudu ngakoni, ora ketompo carane sedih.

Aku ngevaluasi opsi kasebut, nggawe tiket ing Jira kanthi katrangan ing tingkat "saiki ala, lakoni kanthi bener" lan ngrusak tugas kasebut kanthi cepet:

  • nggunakake maneh data,
  • minimalake jumlah gambar maneh,
  • ngilangi panjalukan duplikat,
  • nggawe proses loading luwih jelas.

Ayo nganggo maneh data

Ing teori, rendering sisih server dirancang kanggo ngrampungake rong masalah: ora nandhang watesan mesin telusur ing babagan indeksasi SPA lan nambah metrik FMP (mesthi tambah parah TTI). Ing skenario klasik sing pungkasanipun dirumusake ing Airbnb ing 2013 taun (isih ing Backbone.js), SSR aplikasi JS isomorphic padha mlaku ing lingkungan Node. Server mung ngirim tata letak sing digawe minangka respon kanggo panjaluk kasebut. Banjur rehidrasi dumadi ing sisih klien, lan banjur kabeh bisa tanpa reloads kaca. Kanggo Habr, kaya akeh sumber daya liyane kanthi isi teks, rendering server minangka unsur kritis kanggo mbangun hubungan sing ramah karo mesin telusur.

Senadyan kasunyatan sing luwih saka enem taun wis liwati wiwit tekane saka teknologi, lan ing wektu iki akeh banyu tenan mili ing ngisor kreteg ing ngarep-mburi donya, kanggo akeh pangembang idea iki isih shrouded ing rahasia. Kita ora ngadeg aside lan mbalek metu aplikasi Vue karo support SSR kanggo produksi, ilang siji rinci cilik: kita ora ngirim negara dhisikan kanggo klien.

Kenging punapa? Ora ana jawaban sing tepat kanggo pitakonan iki. Salah siji padha ora pengin nambah ukuran respon saka server, utawa amarga saka Bunch saka masalah arsitektur liyane, utawa mung ora njupuk mati. Siji cara utawa liyane, mbuwang negara lan nggunakake maneh kabeh sing ditindakake server katon cocog lan migunani. Tugas iku sejatine ora pati penting - negara mung nyuntikaken menyang konteks eksekusi, lan Vue kanthi otomatis nambahake menyang tata letak sing digawe minangka variabel global: window.__INITIAL_STATE__.

Salah sawijining masalah sing muncul yaiku ora bisa ngowahi struktur siklik dadi JSON (referensi bunder); ditanggulangi kanthi mung ngganti struktur kasebut karo pasangan sing rata.

Kajaba iku, nalika nangani isi UGC, sampeyan kudu ngelingi yen data kudu diowahi dadi entitas HTML supaya ora ngrusak HTML. Kanggo tujuan kasebut, kita nggunakake he.

Nyilikake redraws

Minangka sampeyan bisa ndeleng saka diagram ing ndhuwur, ing kasus kita, siji Node JS conto nindakake rong fungsi: SSR lan "proxy" ing API, ngendi wewenang pangguna dumadi. Kahanan iki ndadekake ora bisa menehi wewenang nalika kode JS mlaku ing server, amarga simpul siji-Utas, lan fungsi SSR sinkron. Sing, server mung ora bisa ngirim panjalukan kanggo dhewe nalika callstack sibuk karo soko. Ternyata kita nganyari negara, nanging antarmuka ora mandheg, amarga data ing klien kudu dianyari kanthi njupuk sesi pangguna. Kita kudu ngajari aplikasi kita supaya bisa nglebokake data sing bener ing negara wiwitan, kanthi nganggep login pangguna.

Mung ana rong solusi kanggo masalah kasebut:

  • masang data wewenang kanggo panjalukan cross-server;
  • pamisah lapisan Node JS dadi rong conto sing kapisah.

Solusi pisanan mbutuhake panggunaan variabel global ing server, lan sing kapindho ngluwihi wates wektu kanggo ngrampungake tugas paling sethithik sak wulan.

Carane nggawe pilihan? Habr kerep pindhah ing dalan sing paling ora tahan. Secara informal, ana kepinginan umum kanggo nyuda siklus saka ide menyang prototipe dadi minimal. Model sikap menyang produk kaya-kaya kaya postulat saka booking.com, mung bedane yaiku Habr njupuk umpan balik pangguna kanthi luwih serius lan dipercaya sampeyan, minangka pangembang, kanggo nggawe keputusan kasebut.

Sawise logika iki lan kepinginan dhewe kanggo ngatasi masalah kanthi cepet, aku milih variabel global. Lan, kaya sing asring kedadeyan, sampeyan kudu mbayar cepet utawa mengko. Kita mbayar meh langsung: kita kerja ing akhir minggu, mbusak akibat, nulis kirim mortem lan wiwit dibagi server dadi rong bagéan. Kesalahan kasebut bodho banget, lan bug kasebut ora gampang kanggo ngasilake. Ya, isin iki, nanging siji-sijine cara, kesandhung lan groaning, PoCku karo variabel global tetep dadi produksi lan kerjane cukup sukses nalika ngenteni pindhah menyang arsitektur "loro-node" anyar. Iki minangka langkah penting, amarga kanthi resmi tujuane wis digayuh - SSR sinau ngirim kaca sing siap digunakake, lan UI dadi luwih tenang.

Log pangembang ngarep-mburi Habr: refactoring lan nggambarakeAntarmuka Habr Mobile sawise tahap refactoring pisanan

Pungkasane, arsitektur SSR-CSR versi seluler ndadékaké gambar iki:

Log pangembang ngarep-mburi Habr: refactoring lan nggambarakeSirkuit SSR-CSR "loro simpul". Node JS API tansah siap kanggo bedo I / O lan ora diblokir dening fungsi SSR, wiwit pungkasan dumunung ing conto kapisah. Rantai pitakon #3 ora dibutuhake.

Ngilangi panjalukan duplikat

Sawise manipulasi ditindakake, rendering wiwitan kaca ora nyebabake epilepsi maneh. Nanging panggunaan Habr ing mode SPA isih nyebabake kebingungan.

Wiwit basis aliran pangguna yaiku transisi saka formulir daftar artikel → artikel → komentar lan kosok balene, iku penting kanggo ngoptimalake konsumsi sumber saka chain iki ing Panggonan pisanan.

Log pangembang ngarep-mburi Habr: refactoring lan nggambarakeBali menyang feed kirim provokes request data anyar

Ora perlu digali jero. Ing screencast ing ndhuwur sampeyan bisa ndeleng manawa aplikasi njaluk maneh dhaptar artikel nalika ngusap maneh, lan sajrone panyuwunan, kita ora bisa ndeleng artikel kasebut, tegese data sadurunge ilang ing endi wae. Katon kaya komponen dhaptar artikel nggunakake negara lokal lan ilang nalika numpes. Nyatane, aplikasi kasebut nggunakake negara global, nanging arsitektur Vuex dibangun kanthi cepet: modul disambungake menyang kaca, sing banjur disambungake menyang rute. Kajaba iku, kabeh modul "disposable" - saben kunjungan sabanjure menyang kaca nulis ulang kabeh modul:

ArticlesList: [
  { Article1 },
  ...
],
PageArticle: { ArticleFull1 },

Secara total, kita duwe modul Dhaptar Artikel, sing ngemot obyek saka jinis artikel lan modul PageArtikel, sing minangka versi lengkap obyek kasebut artikel, koyo Artikel Lengkap. Umumé, implementasine iki ora nindakake apa-apa sing nggegirisi dhewe - iku gampang banget, bisa uga diarani naif, nanging bisa dingerteni. Yen sampeyan ngreset modul saben-saben sampeyan ngganti rute, sampeyan bisa malah manggon karo. Nanging, obah antarane feed artikel, contone / feed → / kabeh, dijamin uncalan adoh kabeh related kanggo feed pribadi, awit kita mung duwe siji Dhaptar Artikel, ing ngendi sampeyan kudu nglebokake data anyar. Iki maneh ndadékaké kita duplikasi panjalukan.

Sawise ngumpulake kabeh sing bisa dakkandhakake babagan topik kasebut, aku nggawe struktur negara anyar lan menehi menyang kanca-kancaku. Diskusi kasebut dawa, nanging pungkasane argumentasi sing dikarepake ngluwihi keraguan, lan aku miwiti implementasine.

Logika saka solusi paling apik dicethakaké ing rong langkah. Pisanan kita nyoba decouple modul Vuex saka kaca lan ikatan langsung menyang rute. Ya, bakal ana data luwih akeh ing toko, getter bakal dadi luwih rumit, nanging kita ora bakal mbukak artikel kaping pindho. Kanggo versi seluler, iki bisa uga minangka argumen sing paling kuat. Bakal katon kaya iki:

ArticlesList: {
  ROUTE_FEED: [ 
    { Article1 },
    ...
  ],
  ROUTE_ALL: [ 
    { Article2 },
    ...
  ],
}

Nanging apa yen dhaptar artikel bisa tumpang tindih antarane sawetara rute lan apa yen kita pengin nggunakake maneh data obyek artikel kanggo nerjemahake kaca kirim, ngowahi dadi Artikel Lengkap? Ing kasus iki, luwih logis nggunakake struktur kasebut:

ArticlesIds: {
  ROUTE_FEED: [ '1', ... ],
  ROUTE_ALL: [ '1', '2', ... ],
},
ArticlesList: {
  '1': { Article1 }, 
  '2': { Article2 },
  ...
}

Dhaptar Artikel kene iku mung jinis gudang artikel. Kabeh artikel sing diundhuh sajrone sesi pangguna. Kita nambani wong-wong mau kanthi ati-ati, amarga iki minangka lalu lintas sing bisa diunduh liwat nyeri ing endi wae ing metro ing antarane stasiun, lan kita mesthi ora pengin nyebabake rasa lara iki marang pangguna maneh kanthi meksa dheweke mbukak data sing wis ana. diundhuh. Objek ArtikelId iku mung Uploaded saka ID (kaya "pranala") kanggo obyek artikel. Struktur iki ngidini sampeyan supaya ora duplikat data umum kanggo rute lan nggunakake maneh obyek artikel nalika nerjemahake kaca kirim kanthi nggabungake data lengkap.

Output saka dhaptar artikel uga wis dadi luwih transparan: komponen iterator iterates liwat array karo ID artikel lan ndudohke komponen teaser artikel, pass Id minangka prop, lan komponen anak, ing siji, njupuk data sing perlu saka Dhaptar Artikel. Nalika sampeyan pindhah menyang kaca publikasi, kita entuk tanggal sing wis ana Dhaptar Artikel, kita njaluk njaluk data sing ilang lan mung ditambahake menyang obyek sing wis ana.

Napa pendekatan iki luwih apik? Nalika aku nulis ing ndhuwur, pendekatan iki luwih lembut babagan data sing diundhuh lan ngidini sampeyan nggunakake maneh. Nanging saliyane iki, mbukak dalan menyang sawetara kemungkinan anyar sing cocog karo arsitektur kasebut. Contone, polling lan ngemot artikel menyang feed nalika katon. Kita mung bisa nyelehake kiriman paling anyar ing "panyimpenan" Dhaptar Artikel, simpen dhaptar kapisah saka ID anyar ing ArtikelId lan menehi kabar marang pangguna babagan iki. Nalika kita ngeklik tombol "Tampilake publikasi anyar", kita mung bakal nglebokake ID anyar ing wiwitan dhaptar artikel saiki lan kabeh bakal bisa digunakake kanthi ajaib.

Nggawe download luwih nyenengake

Icing ing kue refactoring yaiku konsep kerangka, sing ndadekake proses ngundhuh konten ing Internet alon rada kurang njijiki. Ora ana diskusi babagan perkara iki; dalan saka ide menyang prototipe mbutuhake rong jam. Desain kasebut bisa digambar dhewe, lan kita ngajar komponen supaya bisa nggawe blok div sing gampang, meh ora kedhep nalika ngenteni data. Secara subyektif, pendekatan loading iki bener-bener nyuda jumlah hormon stres ing awak pangguna. Skeleton katon kaya iki:

Log pangembang ngarep-mburi Habr: refactoring lan nggambarake
Habraloading

Refleksi

Aku wis kerja ing Habré nem sasi lan kanca-kanca isih takon: nggih, kados pundi sampeyan seneng ing kana? Oke, nyaman - ya. Nanging ana sing nggawe karya iki beda karo liyane. Aku kerja ing tim sing ora peduli karo produke, ora ngerti utawa ngerti sapa pangguna. Nanging ing kene kabeh beda. Ing kene sampeyan rumangsa tanggung jawab kanggo apa sing ditindakake. Ing proses ngembangake fitur, sampeyan sebagian dadi pemilike, melu kabeh rapat produk sing ana gandhengane karo fungsi sampeyan, menehi saran lan nggawe keputusan dhewe. Nggawe produk sing sampeyan gunakake saben dina apik banget, nanging nulis kode kanggo wong sing bisa uga luwih apik tinimbang sampeyan mung perasaan sing luar biasa (ora sarkasme).

Sawise release saka kabeh owah-owahan iki, kita nampa umpan balik positif, lan iku apik banget. Iku inspirasi. Matur nuwun! Tulis liyane.

Ayo kula ngelingake yen sawise variabel global, kita mutusake kanggo ngganti arsitektur lan ngalokasi lapisan proxy dadi conto sing kapisah. Arsitèktur "loro simpul" wis tekan rilis ing wangun tes beta umum. Saiki sapa wae bisa ngalih lan mbantu kita nggawe Habr seluler luwih apik. Sing kabeh kanggo dina iki. Aku bakal seneng njawab kabeh pitakonan sampeyan ing komentar.

Source: www.habr.com

Add a comment