Log pembangun bahagian hadapan Habr: pemfaktoran semula dan mencerminkan

Log pembangun bahagian hadapan Habr: pemfaktoran semula dan mencerminkan

Saya sentiasa berminat dengan cara Habr distrukturkan dari dalam, cara aliran kerja distrukturkan, cara komunikasi distrukturkan, piawaian yang digunakan dan cara kod umumnya ditulis di sini. Nasib baik, saya mendapat peluang seperti itu, kerana saya baru-baru ini menjadi sebahagian daripada pasukan habra. Menggunakan contoh pemfaktoran semula kecil versi mudah alih, saya akan cuba menjawab soalan: bagaimana rasanya bekerja di sini di hadapan. Dalam program: Node, Vue, Vuex dan SSR dengan sos daripada nota tentang pengalaman peribadi dalam Habr.

Perkara pertama yang anda perlu tahu tentang pasukan pembangunan ialah terdapat sedikit daripada kami. Tidak cukup - ini adalah tiga bahagian hadapan, dua bahagian belakang dan petunjuk teknikal bagi semua Habr - Baxley. Sudah tentu, terdapat juga penguji, pereka bentuk, tiga Vadim, penyapu ajaib, pakar pemasaran dan Bumburum lain. Tetapi terdapat hanya enam penyumbang langsung kepada sumber Habr. Ini agak jarang berlaku - projek dengan penonton berjuta-juta dolar, yang dari luar kelihatan seperti perusahaan gergasi, sebenarnya kelihatan lebih seperti permulaan yang selesa dengan struktur organisasi yang paling rata.

Seperti banyak syarikat IT lain, Habr menyatakan idea Agile, amalan CI, dan itu sahaja. Tetapi menurut perasaan saya, Habr sebagai produk semakin berkembang secara bergelombang daripada secara berterusan. Jadi, untuk beberapa larian pecut berturut-turut, kami bersungguh-sungguh mengekod sesuatu, mereka bentuk dan mereka bentuk semula, memecahkan sesuatu dan membaikinya, menyelesaikan tiket dan mencipta tiket baharu, memijak garu dan menembak diri kami sendiri, untuk akhirnya melepaskan ciri itu ke dalam pengeluaran. Dan kemudiannya tiba masa rehat tertentu, tempoh pembangunan semula, masa untuk melakukan apa yang ada dalam kuadran "penting-bukan mendesak".

Pecutan "luar musim" inilah yang akan dibincangkan di bawah. Kali ini ia termasuk pemfaktoran semula versi mudah alih Habr. Secara umum, syarikat itu menaruh harapan tinggi untuknya, dan pada masa hadapan ia harus menggantikan seluruh zoo jelmaan Habr dan menjadi penyelesaian merentas platform sejagat. Suatu hari nanti akan ada susun atur penyesuaian, PWA, mod luar talian, penyesuaian pengguna, dan banyak lagi perkara menarik.

Mari kita tetapkan tugas

Sekali, pada pendirian biasa, salah satu bahagian hadapan bercakap tentang masalah dalam seni bina komponen komen versi mudah alih. Dengan mengambil kira perkara ini, kami menganjurkan mesyuarat mikro dalam format psikoterapi kumpulan. Semua orang bergilir-gilir mengatakan di mana ia menyakitkan, mereka merakam segala-galanya di atas kertas, mereka bersimpati, mereka memahami, kecuali tiada siapa yang bertepuk tangan. Hasilnya ialah senarai 20 masalah, yang menjelaskan bahawa Habr mudah alih masih mempunyai jalan yang panjang dan berduri untuk berjaya.

Saya terutamanya mengambil berat tentang kecekapan penggunaan sumber dan apa yang dipanggil antara muka yang lancar. Setiap hari, pada laluan rumah-kerja-rumah, saya melihat telefon lama saya bermati-matian cuba memaparkan 20 tajuk berita dalam suapan. Ia kelihatan seperti ini:

Log pembangun bahagian hadapan Habr: pemfaktoran semula dan mencerminkanAntara muka Habr Mudah Alih sebelum pemfaktoran semula

Apa yang berlaku di sini? Ringkasnya, pelayan menyajikan halaman HTML kepada semua orang dengan cara yang sama, tidak kira sama ada pengguna telah log masuk atau tidak. Kemudian JS pelanggan dimuatkan dan meminta data yang diperlukan sekali lagi, tetapi diselaraskan untuk kebenaran. Iaitu, kami sebenarnya melakukan kerja yang sama dua kali. Antara muka berkelip, dan pengguna memuat turun seratus kilobait tambahan yang bagus. Secara terperinci semuanya kelihatan lebih menyeramkan.

Log pembangun bahagian hadapan Habr: pemfaktoran semula dan mencerminkanSkim SSR-CSR lama. Keizinan hanya boleh dilakukan pada peringkat C3 dan C4, apabila Node JS tidak sibuk menjana HTML dan boleh meminta proksi kepada API.

Seni bina kami pada masa itu digambarkan dengan sangat tepat oleh salah seorang pengguna Habr:

Versi mudah alih adalah omong kosong. Saya memberitahunya seperti itu. Gabungan SSR dan CSR yang dahsyat.

Kami terpaksa mengakuinya, tidak kira betapa sedihnya.

Saya menilai pilihan, membuat tiket di Jira dengan penerangan pada tahap "buruk sekarang, lakukan dengan betul" dan menguraikan tugas itu dalam pukulan yang luas:

  • menggunakan semula data,
  • meminimumkan bilangan lukisan semula,
  • menghapuskan permintaan pendua,
  • menjadikan proses pemuatan lebih jelas.

Mari gunakan semula data

Secara teori, rendering sebelah pelayan direka untuk menyelesaikan dua masalah: tidak mengalami keterbatasan enjin carian dari segi pengindeksan SPA dan menambah baik metrik FMP (mesti semakin teruk TTI). Dalam senario klasik yang akhirnya dirumuskan di Airbnb pada 2013 tahun (masih di Backbone.js), SSR ialah aplikasi JS isomorfik yang sama yang dijalankan dalam persekitaran Node. Pelayan hanya menghantar susun atur yang dijana sebagai tindak balas kepada permintaan. Kemudian penghidratan semula berlaku pada bahagian pelanggan, dan kemudian semuanya berfungsi tanpa muat semula halaman. Bagi Habr, seperti banyak sumber lain dengan kandungan teks, pemaparan pelayan adalah elemen kritikal dalam membina hubungan mesra dengan enjin carian.

Walaupun fakta bahawa lebih daripada enam tahun telah berlalu sejak kemunculan teknologi, dan pada masa ini banyak air telah benar-benar mengalir di bawah jambatan di dunia hadapan, bagi kebanyakan pemaju idea ini masih diselubungi kerahsiaan. Kami tidak mengetepikan dan melancarkan aplikasi Vue dengan sokongan SSR kepada pengeluaran, kehilangan satu butiran kecil: kami tidak menghantar keadaan awal kepada pelanggan.

kenapa? Tiada jawapan yang tepat untuk soalan ini. Sama ada mereka tidak mahu meningkatkan saiz respons daripada pelayan, atau kerana banyak masalah seni bina yang lain, atau ia hanya tidak berlepas. Satu cara atau yang lain, membuang keadaan dan menggunakan semula semua yang dilakukan oleh pelayan nampaknya agak sesuai dan berguna. Tugas itu sebenarnya remeh - negeri hanya disuntik ke dalam konteks pelaksanaan, dan Vue secara automatik menambahkannya pada susun atur yang dijana sebagai pembolehubah global: window.__INITIAL_STATE__.

Salah satu masalah yang timbul ialah ketidakupayaan untuk menukar struktur kitaran kepada JSON (rujukan pekeliling); telah diselesaikan dengan hanya menggantikan struktur tersebut dengan rekaan rata mereka.

Di samping itu, apabila berurusan dengan kandungan UGC, anda harus ingat bahawa data harus ditukar kepada entiti HTML agar tidak memecahkan HTML. Untuk tujuan ini kami gunakan he.

Meminimumkan lukisan semula

Seperti yang anda boleh lihat daripada rajah di atas, dalam kes kami, satu contoh Node JS melaksanakan dua fungsi: SSR dan "proksi" dalam API, di mana kebenaran pengguna berlaku. Keadaan ini menjadikannya mustahil untuk membenarkan semasa kod JS berjalan pada pelayan, kerana nod adalah satu-benang, dan fungsi SSR adalah segerak. Iaitu, pelayan tidak boleh menghantar permintaan kepada dirinya sendiri semasa callstack sibuk dengan sesuatu. Ternyata kami mengemas kini keadaan, tetapi antara muka tidak berhenti berkedut, kerana data pada klien perlu dikemas kini dengan mengambil kira sesi pengguna. Kami perlu mengajar aplikasi kami untuk meletakkan data yang betul dalam keadaan awal, dengan mengambil kira log masuk pengguna.

Terdapat hanya dua penyelesaian kepada masalah itu:

  • lampirkan data kebenaran pada permintaan silang pelayan;
  • pecahkan lapisan Node JS kepada dua kejadian berasingan.

Penyelesaian pertama memerlukan penggunaan pembolehubah global pada pelayan, dan yang kedua melanjutkan tarikh akhir untuk menyelesaikan tugas sekurang-kurangnya sebulan.

Bagaimana untuk membuat pilihan? Habr sering bergerak di sepanjang jalan yang paling sedikit tentangan. Secara tidak formal, terdapat keinginan umum untuk mengurangkan kitaran daripada idea kepada prototaip kepada minimum. Model sikap terhadap produk agak mengingatkan postulat booking.com, dengan satu-satunya perbezaan ialah Habr mengambil maklum balas pengguna dengan lebih serius dan mempercayai anda, sebagai pembangun, untuk membuat keputusan sedemikian.

Berikutan logik ini dan keinginan saya sendiri untuk menyelesaikan masalah dengan cepat, saya memilih pembolehubah global. Dan, seperti yang sering berlaku, anda perlu membayarnya lambat laun. Kami membayar hampir serta-merta: kami bekerja pada hujung minggu, membersihkan akibatnya, menulis bedah siasat dan mula membahagikan pelayan kepada dua bahagian. Ralat itu sangat bodoh, dan pepijat yang melibatkannya tidak mudah untuk dihasilkan semula. Dan ya, ia memalukan untuk ini, tetapi satu cara atau yang lain, tersandung dan mengerang, PoC saya dengan pembolehubah global tetap masuk ke dalam pengeluaran dan berfungsi dengan agak berjaya sementara menunggu perpindahan ke seni bina "dua nod" yang baharu. Ini adalah langkah penting, kerana secara rasmi matlamat telah dicapai - SSR belajar untuk menyampaikan halaman yang sedia untuk digunakan sepenuhnya, dan UI menjadi lebih tenang.

Log pembangun bahagian hadapan Habr: pemfaktoran semula dan mencerminkanAntara muka Habr Mudah Alih selepas peringkat pertama pemfaktoran semula

Akhirnya, seni bina SSR-CSR versi mudah alih membawa kepada gambar ini:

οΏΌLog pembangun bahagian hadapan Habr: pemfaktoran semula dan mencerminkanLitar SSR-CSR "Dua nod". API Node JS sentiasa bersedia untuk I/O tak segerak dan tidak disekat oleh fungsi SSR, kerana yang kedua terletak dalam keadaan berasingan. Rantaian pertanyaan #3 tidak diperlukan.

Menghapuskan permintaan pendua

Selepas manipulasi dilakukan, pemaparan awal halaman tidak lagi menimbulkan epilepsi. Tetapi penggunaan selanjutnya Habr dalam mod SPA masih menyebabkan kekeliruan.

Oleh kerana asas aliran pengguna adalah peralihan bentuk senarai artikel β†’ artikel β†’ ulasan dan sebaliknya, adalah penting untuk mengoptimumkan penggunaan sumber rantaian ini pada mulanya.

Log pembangun bahagian hadapan Habr: pemfaktoran semula dan mencerminkanKembali ke suapan siaran mencetuskan permintaan data baharu

Tidak perlu menggali dalam-dalam. Dalam siaran skrin di atas anda dapat melihat bahawa aplikasi meminta semula senarai artikel apabila meleret ke belakang, dan semasa permintaan kami tidak melihat artikel, yang bermaksud data sebelumnya hilang entah ke mana. Nampaknya komponen senarai artikel menggunakan keadaan setempat dan kehilangannya apabila dimusnahkan. Malah, aplikasi itu menggunakan keadaan global, tetapi seni bina Vuex dibina secara langsung: modul terikat pada halaman, yang seterusnya terikat pada laluan. Selain itu, semua modul adalah "boleh guna" - setiap lawatan berikutnya ke halaman menulis semula keseluruhan modul:

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

Secara keseluruhan, kami mempunyai modul Senarai Artikel, yang mengandungi objek jenis Artikel dan modul HalamanArtikel, yang merupakan versi lanjutan objek Artikel, macam ArtikelPenuh. Pada umumnya, pelaksanaan ini tidak membawa apa-apa yang mengerikan dengan sendirinya - ia sangat mudah, bahkan mungkin dikatakan naif, tetapi sangat mudah difahami. Jika anda menetapkan semula modul setiap kali anda menukar laluan, maka anda juga boleh hidup dengannya. Walau bagaimanapun, bergerak antara suapan artikel, sebagai contoh / suapan β†’ /semua, dijamin akan membuang semua yang berkaitan dengan suapan peribadi, kerana kami hanya mempunyai satu Senarai Artikel, di mana anda perlu memasukkan data baharu. Ini sekali lagi membawa kita kepada pertindihan permintaan.

Setelah mengumpulkan semua yang saya dapat gali mengenai topik itu, saya merumuskan struktur negeri baru dan membentangkannya kepada rakan sekerja saya. Perbincangan adalah panjang, tetapi akhirnya hujah yang menyokong mengatasi keraguan, dan saya mula melaksanakan.

Logik penyelesaian paling baik didedahkan dalam dua langkah. Mula-mula kita cuba memisahkan modul Vuex daripada halaman dan mengikat terus ke laluan. Ya, akan ada lebih sedikit data di kedai, getter akan menjadi lebih kompleks sedikit, tetapi kami tidak akan memuatkan artikel dua kali. Untuk versi mudah alih, ini mungkin hujah yang paling kuat. Ia akan kelihatan seperti ini:

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

Tetapi bagaimana jika senarai artikel boleh bertindih antara berbilang laluan dan bagaimana jika kita mahu menggunakan semula data objek Artikel untuk memaparkan halaman siaran, mengubahnya menjadi ArtikelPenuh? Dalam kes ini, lebih logik untuk menggunakan struktur sedemikian:

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

Senarai Artikel di sini ia hanyalah sejenis repositori artikel. Semua artikel yang dimuat turun semasa sesi pengguna. Kami melayan mereka dengan penuh berhati-hati, kerana ini adalah trafik yang mungkin telah dimuat turun melalui kesakitan di suatu tempat di metro antara stesen, dan kami pasti tidak mahu menyebabkan kesakitan ini kepada pengguna lagi dengan memaksanya memuatkan data yang telah dia miliki. dimuat turun. Sebuah objek ArtikelId hanyalah tatasusunan ID (seolah-olah "pautan") kepada objek Artikel. Struktur ini membolehkan anda mengelakkan penduaan data biasa untuk laluan dan menggunakan semula objek Artikel apabila memaparkan halaman siaran dengan menggabungkan data lanjutan ke dalamnya.

Output senarai artikel juga menjadi lebih telus: komponen iterator berulang melalui tatasusunan dengan ID artikel dan melukis komponen penggoda artikel, menghantar Id sebagai prop, dan komponen anak, seterusnya, mendapatkan semula data yang diperlukan daripada Senarai Artikel. Apabila anda pergi ke halaman penerbitan, kami mendapat tarikh sedia ada daripada Senarai Artikel, kami membuat permintaan untuk mendapatkan data yang hilang dan hanya menambahnya pada objek sedia ada.

Mengapa pendekatan ini lebih baik? Seperti yang saya tulis di atas, pendekatan ini lebih lembut berkenaan dengan data yang dimuat turun dan membolehkan anda menggunakannya semula. Tetapi selain itu, ia membuka jalan kepada beberapa kemungkinan baharu yang sesuai dengan seni bina sedemikian. Contohnya, mengundi dan memuatkan artikel ke dalam suapan apabila ia muncul. Kami hanya boleh meletakkan siaran terkini dalam "storan" Senarai Artikel, simpan senarai berasingan ID baharu dalam ArtikelId dan memberitahu pengguna mengenainya. Apabila kami mengklik pada butang "Tunjukkan penerbitan baharu", kami hanya akan memasukkan Id baharu ke dalam permulaan tatasusunan senarai artikel semasa dan semuanya akan berfungsi hampir secara ajaib.

Menjadikan muat turun lebih menyeronokkan

Ais pada kek pemfaktoran semula adalah konsep rangka, yang menjadikan proses memuat turun kandungan pada Internet perlahan kurang menjijikkan. Tiada perbincangan mengenai perkara ini; laluan dari idea kepada prototaip mengambil masa dua jam. Reka bentuk ini boleh dilukis sendiri, dan kami mengajar komponen kami untuk membuat blok div yang mudah dan hampir tidak berkelip semasa menunggu data. Secara subjektif, pendekatan pemuatan ini sebenarnya mengurangkan jumlah hormon tekanan dalam badan pengguna. Rangka kelihatan seperti ini:

Log pembangun bahagian hadapan Habr: pemfaktoran semula dan mencerminkan
Habraloading

Merenung

Saya telah bekerja di HabrΓ© selama enam bulan dan rakan-rakan saya masih bertanya: baik, bagaimana anda menyukainya di sana? Okay, selesa - ya. Tetapi ada sesuatu yang membuat kerja ini berbeza daripada yang lain. Saya bekerja dalam pasukan yang langsung tidak peduli dengan produk mereka, tidak tahu atau memahami siapa pengguna mereka. Tetapi di sini semuanya berbeza. Di sini anda berasa bertanggungjawab terhadap apa yang anda lakukan. Dalam proses membangunkan ciri, anda sebahagiannya menjadi pemiliknya, mengambil bahagian dalam semua mesyuarat produk yang berkaitan dengan fungsi anda, membuat cadangan dan membuat keputusan sendiri. Membuat produk yang anda gunakan sendiri setiap hari adalah sangat keren, tetapi menulis kod untuk orang yang mungkin lebih baik daripada anda hanyalah perasaan yang luar biasa (tiada sindiran).

Selepas keluaran semua perubahan ini, kami menerima maklum balas positif, dan ia sangat, sangat bagus. Ia memberi inspirasi. Terima kasih! Tulis lagi.

Biar saya ingatkan anda bahawa selepas pembolehubah global kami memutuskan untuk menukar seni bina dan memperuntukkan lapisan proksi ke dalam contoh yang berasingan. Seni bina "dua nod" telah pun mencapai keluaran dalam bentuk ujian beta awam. Kini sesiapa sahaja boleh beralih kepadanya dan membantu kami menjadikan Habr mudah alih lebih baik. Itu sahaja untuk hari ini. Saya dengan senang hati akan menjawab semua soalan anda dalam komen.

Sumber: www.habr.com

Tambah komen