Habr алдыңғы қатарлы әзірлеуші ​​журналдары: рефакторинг және шағылысатын

Habr алдыңғы қатарлы әзірлеуші ​​журналдары: рефакторинг және шағылысатын

Мені әрқашан Хабрдың ішінен қалай құрылымдайтыны, жұмыс процесі қалай құрылымдалғаны, коммуникациялар қалай құрылымдалғаны, қандай стандарттар қолданылатыны және жалпы код қалай жазылғаны қызықтырды. Бақытымызға орай, мен осындай мүмкіндікке ие болдым, өйткені мен жақында хабра командасының мүшесі болдым. Мобильді нұсқаның шағын рефакторингінің мысалын қолдана отырып, мен сұраққа жауап беруге тырысамын: мұнда майданда жұмыс істеу қандай? Бағдарламада: Node, Vue, Vuex және SSR Хабрдағы жеке тәжірибе туралы жазбалардан алынған соусы бар.

Әзірлеу тобы туралы білуіңіз керек бірінші нәрсе - бізде аз. Жеткіліксіз - бұл үш фронт, екі артқы және барлық Хабрдың техникалық жетекші - Баксли. Сондай-ақ, әрине, сынақшы, дизайнер, үш Вадим, ғажайып сыпырғыш, маркетинг маманы және басқа да Бумбурумдар бар. Бірақ Хабрдың көздеріне тек алты тікелей қатысушы бар. Бұл өте сирек – көп миллиондық аудиториясы бар жоба, ол сырттан алып кәсіпорынға ұқсайды, ал шындығында ұйымдық құрылымы мүмкін болатын жайлы стартапқа көбірек ұқсайды.

Көптеген басқа IT-компаниялар сияқты, Хабр Agile идеяларын, CI тәжірибесін айтады және барлығы осы. Бірақ менің сезімім бойынша, Хабр өнім ретінде үздіксіз емес, толқындар түрінде дамиды. Осылайша, қатарынан бірнеше спринт үшін біз бір нәрсені мұқият кодтаймыз, жобалаймыз және қайта өңдейміз, бірдеңені бұзып, түзетеміз, билеттерді шешеміз және жаңасын жасаймыз, рейске басып, аяғымызға оқ атамыз, осылайша функцияны ақырында шығаруға болады. өндіріс. Содан кейін белгілі бір тыныштық, қайта құру кезеңі, «маңызды-шұғыл емес» квадранттағы нәрсені істеу уақыты келеді.

Дәл осы «маусымнан тыс» спринт төменде талқыланады. Бұл жолы ол Хабрдың мобильді нұсқасының рефакторингін қамтыды. Жалпы, компания оған үлкен үміт артады және болашақта ол Хабрдың инкарнацияларының бүкіл хайуанаттар бағын ауыстырып, әмбебап кросс-платформалық шешімге айналуы керек. Бір күні адаптивті орналасу, PWA, офлайн режимі, пайдаланушыны теңшеу және басқа да көптеген қызықты нәрселер болады.

Тапсырманы қояйық

Бірде, кәдімгі стендте, алдыңғылардың бірі мобильді нұсқаның түсініктемелер құрамдас бөлігінің архитектурасындағы проблемалар туралы айтты. Осыны ескере отырып, топтық психотерапия форматында шағын отырыс ұйымдастырдық. Қай жері ауырса, бәрі кезек-кезек айтып, бәрін қағазға түсірді, жанашырлық танытты, түсінді, тек ешкім қол соққан жоқ. Нәтиже 20 мәселенің тізімі болды, бұл мобильді Хабрдың әлі де табысқа жетудің ұзақ және қиын жолы бар екенін көрсетті.

Мені ең алдымен ресурс тиімділігі және тегіс интерфейс деп аталатын нәрсе алаңдатты. Күн сайын үй-жұмыс-үй бағытында мен ескі телефонымның арнада 20 тақырыпты көрсетуге тырысып жатқанын көрдім. Бұл келесідей көрінді:

Habr алдыңғы қатарлы әзірлеуші ​​журналдары: рефакторинг және шағылысатынМобильді Habr интерфейсі рефакторингке дейін

Бұл жерде не болып жатыр? Қысқасы, сервер HTML бетін пайдаланушының жүйеге кірген-кірмегеніне қарамастан барлығына бірдей қызмет етті. Содан кейін клиент JS жүктеледі және қажетті деректерді қайтадан сұрайды, бірақ авторизациялау үшін реттеледі. Яғни, біз бір жұмысты екі рет жасадық. Интерфейс жыпылықтап, пайдаланушы жақсы жүз қосымша килобайт жүктеп алды. Егжей-тегжейлі бәрі одан да қорқынышты көрінді.

Habr алдыңғы қатарлы әзірлеуші ​​журналдары: рефакторинг және шағылысатынЕскі SSR-CSR схемасы. Авторизация тек C3 және C4 кезеңдерінде мүмкін болады, бұл кезде JS түйіні HTML жасаумен бос емес және API сұрауларын прокси арқылы жібере алады.

Біздің сол кездегі архитектураны Хабр қолданушыларының бірі өте дәл сипаттаған:

Мобильді нұсқасы ақымақ. Мен оны солай айтып жатырмын. SSR және CSR қорқынышты үйлесімі.

Қанша мұң болса да мойындауға тура келді.

Мен опцияларды бағаладым, Jira-да «қазір жаман, дұрыс істе» деңгейіндегі сипаттамасы бар билет жасадым және тапсырманы кең штрихтармен бөлдім:

  • деректерді қайта пайдалану,
  • қайта сызу санын азайту,
  • қайталанатын сұрауларды жою,
  • жүктеу процесін айқынырақ етеді.

Деректерді қайта қолданайық

Теориялық тұрғыдан серверлік рендеринг екі мәселені шешуге арналған: іздеу жүйесінің шектеулерінен зардап шекпеу. SPA индекстеу және метриканы жақсарту FMP (міндетті түрде нашарлайды TTI). Классикалық сценарийде бұл ақыры Airbnb-де 2013 жылы тұжырымдалған жылы (әлі Backbone.js жүйесінде), SSR түйін ортасында жұмыс істейтін бірдей изоморфты JS қолданбасы. Сервер сұранысқа жауап ретінде жасалған орналасуды жай ғана жібереді. Содан кейін клиент жағында регидратация жүреді, содан кейін бәрі бетті қайта жүктеусіз жұмыс істейді. Хабр үшін, мәтіндік мазмұны бар көптеген басқа ресурстар сияқты, серверді көрсету іздеу жүйелерімен достық қарым-қатынас орнатудың маңызды элементі болып табылады.

Технологияның пайда болуынан алты жылдан астам уақыт өткеніне және осы уақыт ішінде алдыңғы әлемде көпірдің астынан көп су ағып кеткеніне қарамастан, көптеген әзірлеушілер үшін бұл идея әлі де құпия болып табылады. Біз шетте қалмадық және SSR қолдауы бар Vue қосымшасын өндіріске шығардық, бір ұсақ бөлшектерді жіберіп алды: біз клиентке бастапқы күйді жібермедік.

Неліктен? Бұл сұраққа нақты жауап жоқ. Немесе олар серверден жауаптың өлшемін ұлғайтқысы келмеді, немесе басқа да архитектуралық мәселелерге байланысты, немесе ол жай ғана шешілмеді. Қалай болғанда да, күйді жою және сервер жасаған барлық нәрсені қайта пайдалану өте орынды және пайдалы болып көрінеді. Тапсырма шын мәнінде тривиальды - күй жай ғана енгізіледі орындау контекстіне және Vue оны автоматты түрде жаһандық айнымалы ретінде жасалған орналасуға қосады: window.__INITIAL_STATE__.

Пайда болған мәселелердің бірі - циклдік құрылымдарды JSON-ға түрлендіру мүмкін емес (дөңгелек сілтеме); мұндай құрылымдарды жай ғана олардың тегіс ұқсастарымен ауыстыру арқылы шешілді.

Сонымен қатар, UGC мазмұнымен жұмыс істегенде, HTML-ді бұзбау үшін деректерді HTML нысандарына түрлендіру керек екенін есте ұстаған жөн. Осы мақсаттар үшін біз пайдаланамыз he.

Қайта сызуларды азайту

Жоғарыдағы диаграммадан көріп отырғаныңыздай, біздің жағдайда бір Node JS данасы екі функцияны орындайды: SSR және пайдаланушы авторизациясы орын алатын API ішіндегі «прокси». Бұл жағдай JS коды серверде жұмыс істеп тұрған кезде авторизациялауды мүмкін емес етеді, себебі түйін бір ағынды және SSR функциясы синхронды. Яғни, қоңыраулар стек бірдеңемен бос емес кезде сервер өзіне сұрау жібере алмайды. Біз күйді жаңартқанымыз белгілі болды, бірақ интерфейс тітіркенуді тоқтатпады, өйткені клиенттегі деректер пайдаланушы сеансын ескере отырып жаңартылуы керек болды. Біз қолданбамызды пайдаланушының логинін ескере отырып, дұрыс деректерді бастапқы күйге қоюды үйретуіміз керек еді.

Мәселенің екі ғана шешімі болды:

  • сервераралық сұрауларға авторизация деректерін тіркеңіз;
  • Node JS қабаттарын екі бөлек данаға бөліңіз.

Бірінші шешім серверде жаһандық айнымалы мәндерді пайдалануды талап етті, ал екіншісі тапсырманы орындау мерзімін кемінде бір айға ұзартты.

Қалай таңдау жасауға болады? Хабр жиі ең аз қарсылық жолымен қозғалады. Бейресми түрде идеядан прототипке дейінгі циклді минимумға дейін қысқартуға жалпы ұмтылыс бар. Өнімге деген көзқарас үлгісі booking.com постулаттарын біршама еске түсіреді, жалғыз айырмашылығы - Хабр пайдаланушылардың пікірін әлдеқайда байыпты қабылдайды және әзірлеуші ​​ретінде сізге осындай шешімдер қабылдауға сенеді.

Осы логика мен мәселені тез шешуге деген өз қалауымды ескере отырып, мен жаһандық айнымалыларды таңдадым. Және, әдетте, сіз олар үшін ерте ме, кеш пе төлеуге тура келеді. Біз дерлік төледік: біз демалыс күндері жұмыс істедік, салдарын жойдық, деп жазды кейінгі өлім және серверді екі бөлікке бөле бастады. Қате өте ақымақ болды және оны қамтитын қатені қайта шығару оңай болмады. Иә, бұл ұят, бірақ қандай да бір жолмен, сүрініп, ыңылдап, менің жаһандық айнымалылары бар PoC әлі де өндіріске кірді және жаңа «екі түйінді» архитектураға көшуді күту кезінде сәтті жұмыс істейді. Бұл маңызды қадам болды, өйткені ресми түрде мақсатқа қол жеткізілді - SSR толығымен пайдалануға дайын бетті жеткізуді үйренді, ал UI әлдеқайда тыныш болды.

Habr алдыңғы қатарлы әзірлеуші ​​журналдары: рефакторинг және шағылысатынРефакторингтің бірінші кезеңінен кейінгі Mobile Habr интерфейсі

Сайып келгенде, мобильді нұсқаның SSR-CSR архитектурасы мына суретке әкеледі:

Habr алдыңғы қатарлы әзірлеуші ​​журналдары: рефакторинг және шағылысатын«Екі түйінді» SSR-CSR схемасы. Node JS API әрқашан асинхронды енгізу/шығару үшін дайын және SSR функциясымен блокталмайды, себебі соңғысы бөлек данада орналасқан. №3 сұрау тізбегі қажет емес.

Қайталанатын сұрауларды жою

Манипуляциялар жасалғаннан кейін беттің бастапқы көрінісі эпилепсияны тудырмады. Бірақ SPA режимінде Хабрды одан әрі пайдалану әлі де шатастыруды тудырды.

Өйткені пайдаланушы ағынының негізі форманың ауысуы болып табылады мақалалар тізімі → мақала → пікірлер және керісінше, бірінші кезекте осы тізбектің ресурстарын тұтынуды оңтайландыру маңызды болды.

Habr алдыңғы қатарлы әзірлеуші ​​журналдары: рефакторинг және шағылысатынЖазба арнасына оралу жаңа деректер сұрауын тудырады

Терең қазудың қажеті жоқ еді. Жоғарыдағы скринкастта сіз артқа сырғыған кезде қолданба мақалалар тізімін қайта сұрайтынын көре аласыз, ал сұрау кезінде біз мақалаларды көрмейміз, яғни алдыңғы деректер бір жерде жоғалып кетеді. Мақалалар тізімінің құрамдас бөлігі жергілікті күйді қолданып, жою кезінде оны жоғалтатын сияқты. Шындығында, қолданба жаһандық күйді пайдаланды, бірақ Vuex архитектурасы бір-бірімен байланысты болды: модульдер беттерге, олар өз кезегінде маршруттарға байланыстырылған. Сонымен қатар, барлық модульдер «бір реттік» - бетке әрбір келесі кіру модульді қайта жазды:

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

Жалпы бізде модуль болды Мақалалар тізімітүріндегі нысандарды қамтитын мақала және модуль Бет мақаласы, бұл нысанның кеңейтілген нұсқасы болды мақала, сияқты Мақала толық. Тұтастай алғанда, бұл іске асырудың өзінде қорқынышты ештеңе жоқ - бұл өте қарапайым, тіпті аңғал деп айтуға болады, бірақ өте түсінікті. Егер сіз маршрутты өзгерткен сайын модульді қалпына келтірсеңіз, онымен өмір сүре аласыз. Дегенмен, мысалы, мақала арналары арасында жылжу /арна → /барлығы, жеке арнаға қатысты барлық нәрсені тастауға кепілдік беріледі, өйткені бізде тек біреуі ғана бар Мақалалар тізімі, оған жаңа деректерді енгізу керек. Бұл тағы да сұраулардың қайталануына әкеледі.

Тақырып бойынша қазбалай білгеннің бәрін жинақтап, жаңа мемлекеттік құрылымды тұжырымдап, әріптестеріме ұсындым. Талқылаулар ұзақ болды, бірақ соңында пайдасына дәлелдер күмәндан асып түсті, мен жүзеге асыруға кірістім.

Шешімнің логикасы екі қадамда жақсы ашылады. Алдымен біз Vuex модулін беттерден ажыратып, маршруттарға тікелей байланыстыруға тырысамыз. Иә, дүкенде деректер аздап көп болады, алғыштар сәл күрделірек болады, бірақ біз мақалаларды екі рет жүктемейміз. Мобильді нұсқа үшін бұл ең күшті дәлел болуы мүмкін. Ол келесідей болады:

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

Бірақ мақала тізімдері бірнеше бағыттар арасында қабаттасуы мүмкін болса және нысан деректерін қайта пайдаланғымыз келсе ше? мақала пост бетін түрлендіру үшін Мақала толық? Бұл жағдайда мұндай құрылымды пайдалану қисынды болады:

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

Мақалалар тізімі мұнда бұл жай ғана мақалалар қоймасының бір түрі. Пайдаланушы сеансы кезінде жүктелген барлық мақалалар. Біз оларға аса сақтықпен қараймыз, өйткені бұл станциялар арасындағы метроның бір жерінде ауырсыну арқылы жүктеп алынған трафик, және біз оны пайдаланушыға бұрыннан бар деректерді жүктеуге мәжбүрлеу арқылы оны қайтадан ауыртқымыз келмейді. жүктелді. Объект Мақалалар идентификаторлары жай ғана идентификаторлардың массиві («сілтемелер» сияқты) нысандарға мақала. Бұл құрылым маршруттарға ортақ деректердің қайталануын болдырмауға және нысанды қайта пайдалануға мүмкіндік береді мақала кеңейтілген деректерді біріктіру арқылы хабарлама бетін көрсету кезінде.

Мақалалар тізімінің шығысы да мөлдір болды: итератор құрамдас бөлігі мақала идентификаторлары бар массив арқылы итерацияланады және идентификаторды тірек ретінде өткізе отырып, мақала тизер компонентін салады, ал еншілес компонент, өз кезегінде, қажетті деректерді шығарады. Мақалалар тізімі. Жарияланым бетіне өтсеңіз, бұрыннан бар күнді аламыз Мақалалар тізімі, біз жетіспейтін деректерді алу үшін сұраныс жасаймыз және оны бар нысанға қосамыз.

Неліктен бұл тәсіл жақсырақ? Жоғарыда жазғанымдай, бұл әдіс жүктелген деректерге қатысты жұмсақ және оны қайта пайдалануға мүмкіндік береді. Бірақ бұдан басқа, ол мұндай сәулетке тамаша сәйкес келетін кейбір жаңа мүмкіндіктерге жол ашады. Мысалы, мақалаларды пайда болған кезде сұрау және арнаға жүктеу. Біз жай ғана соңғы жазбаларды «жадқа» қоя аламыз. Мақалалар тізімі, жаңа идентификаторлардың бөлек тізімін сақтаңыз Мақалалар идентификаторлары және бұл туралы пайдаланушыға хабарлаңыз. «Жаңа жарияланымдарды көрсету» түймесін басқан кезде, біз жай ғана мақалалар тізімінің массивінің басына жаңа идентификаторларды енгіземіз және бәрі сиқырлы түрде жұмыс істейді.

Жүктеп алуды қызықты ету

Рефакторинг тортындағы глазурь - бұл қаңқалар тұжырымдамасы, ол баяу Интернетте мазмұнды жүктеу процесін біршама жиіркенішті етеді. Бұл мәселе бойынша талқылаулар болған жоқ; идеядан прототипке дейінгі жол екі сағатқа созылды. Дизайн іс жүзінде өзін сызды және біз өз компоненттерімізді деректерді күту кезінде қарапайым, әрең жыпылықтайтын div блоктарын көрсетуге үйреттік. Субъективті түрде жүктеудің бұл тәсілі пайдаланушының денесінде стресс гормондарының мөлшерін азайтады. Қаңқа келесідей көрінеді:

Habr алдыңғы қатарлы әзірлеуші ​​журналдары: рефакторинг және шағылысатын
Habraloading

Рефлексия

Мен Хабреде алты ай жұмыс істеп жатырмын, бірақ менің достарым әлі де сұрайды: ол жер сізге қалай ұнайды? Жарайды, ыңғайлы - иә. Бірақ бұл жұмысты басқалардан ерекшелендіретін бір нәрсе бар. Мен өз өніміне мүлдем бей-жай қарамайтын, пайдаланушыларының кім екенін білмейтін немесе түсінбейтін командаларда жұмыс істедім. Бірақ мұнда бәрі басқаша. Мұнда сіз өз ісіңізге жауапкершілікті сезінесіз. Функцияны әзірлеу барысында сіз ішінара оның иесі боласыз, функционалдық мүмкіндіктеріңізге қатысты барлық өнім жиналыстарына қатысасыз, ұсыныстар енгізіп, шешім қабылдайсыз. Күнделікті өзіңіз қолданатын өнімді өзіңіз жасау өте керемет, бірақ сізден жақсырақ адамдар үшін код жазу - бұл керемет сезім (мысқылсыз).

Осы өзгерістердің барлығын шығарғаннан кейін біз оң пікірлер алдық және бұл өте жақсы болды. Бұл шабыттандырады. Рақмет сізге! Көбірек жазыңыз.

Жаһандық айнымалылардан кейін біз архитектураны өзгертуге және прокси деңгейін бөлек данаға бөлуге шешім қабылдағанымызды еске саламын. «Екі түйінді» архитектурасы көпшілікке арналған бета-тестілеу түрінде шығарылымға жетті. Енді кез келген адам оған ауысып, мобильді Habr қолданбасын жақсартуға көмектесе алады. Бүгінгі күннің бәрі осы. Мен сіздің барлық сұрақтарыңызға түсініктемелерде жауап беруге қуаныштымын.

Ақпарат көзі: www.habr.com

пікір қалдыру