JavaScript-only: гомогенна архітектура веб-проектів

Робота фронтенд-розробника наповнена завданнями щодо оптимізації коду, перенесення готових фрагментів між версіями проектів і т. п., складність яких найчастіше визначається історично сформованим підходом до самої розробки. У своїй доповіді на конференції HolyJS, яка відбудеться 5 червня в Санкт-Петербурзі, фронтенд-розробник Олексій Іванов розповість, як обсяг цих проблем можна скоротити відмовою від звичного підходу, коли програма складається з розрізнених частин, на користь «все-в-JS». Ми ж напередодні конференції поговорили з Олексієм про те, від яких саме труднощів позбавляють запропоновані ним ідеї (самі ідеї будуть детальніше розкрито у доповіді).



— Розкажи коротко про себе та своєї роботи.

— Мене звати Олексій Іванов, я фронтенд-розробник в компанії «Злі марсіани» (Evil Martians). Це розподілена група розробників, допомагає великим компаніям, зразок eBay або Groupon, а також різним стартапам в короткі терміни і без проблем запускати інтернет-проекти з розрахунком на швидке зростання.
У Марсіан я зараз займаюся фронтендом сервісу під назвою eBay Social для російського офісу eBay. Це класичне додаток на Ruby on Rails з окремими інтерактивними частинами, написаними на React.
До Марсіан я робив першу версію SPA-програми для ridero.ru на Backbone, допомагав запускати кілька сервісів для Яндекса з використанням bem-tools, а також займався розробкою інших серверних і SPA-програм різного розміру, що дозволило мені помацати купу різних інструментів і методологій розробки. Мені подобається вивчати і порівнювати різні способи організації коду, роботи з залежностями і вирішення конфліктів, що використовуються в різних методологіях та інструментах.

Звідки взагалі з'явилася ідея про якусь глобальну зміну підходу до розробки?

— Фронтендеры Марсіан працюють з двома основними типами проектів.
По-перше, ми створюємо класичні проекти на Ruby on Rails. В таких проектах рендер шаблонів відбувається на сервері всередині самих Rails, а збірка CSS і JavaScript живе окремо Node.js і Gulp'е або іншому збирача. Ми користуємося пре — і постпроцесорами, збираємо окремі файли на спільні бандли і стискаємо код Clean CSS і UglifyJS, але при цьому CSS і JavaScript один про одного знають дуже мало, а про HTML, з яким вони працюють, взагалі нічого не знають.

По-друге, ми створюємо односторінкові додатки (SPA), які будують HTML, а часто і CSS одразу в браузері, і з сервером спілкуються тільки на рівні даних.
По суті, це два паралельні світи в сучасному фронтенде. У якийсь момент SPA відбрунькувалися від класичних серверних додатків в окрему еволюційну гілку і пішли власним шляхом зі своїм набором мутацій і нових ідей. В результаті набір інструментів, який використовується на цих двох типах проектів, сильно розрізняється.

Інструменти та підходи, використовувані в сучасних SPA, дозволяють з мінімальними зусиллями вирішувати багато класичні проблеми фронтенд-розробки: перетин назв змінних і CSS-класів у глобальному просторі імен, вилучення невикористаного коду і стилів, створення збірок CSS і JavaScript під конкретні розділи та сторінки. Найприємніше те, що основну частину роботи тут за вас робить машина при мінімальному втручанні.

Тому повернення до класичних серверним додаткам після роботи з SPA викликає біль і страждання. Речі, які в SPA працювали з коробки, тепер або не працюють, або вимагають для реалізації купу часу і сил.

Як нормальна людина, я шукаю способи позбутися від болю і страждань. І моя доповідь являє собою результати цих пошуків. Я хочу розповісти про існуючі проблеми, способи їх вирішення в SPA, інструментах, які з'явилися в СПА, але які цілком можна застосовувати і на сервері, а також про концепціях з SPA, які поки для серверних додатків не реалізовані у вигляді готового софта (однак у випадку реалізації софта вони допомогли б вирішити багато невирішені проблеми зараз).

— чи ти Можеш навести приклади згаданих проблем, властивих розробки серверних додатків?

— У великих проектах існує ряд завдань, що стосуються оптимізації швидкості завантаження і зменшення обсягу коду, який відправляється в браузер.

Припустимо, ми відправляємо користувачеві сторінки HTML, CSS і JavaScript. CSS у нас написаний за методологією БЕМ. Один із способів оптимізації — скорочення довгих імен в CSS, які ми при розробці написали для себе, щоб уникнути конфліктів з іншими класами.

Припустимо, у нас є клас:

.block__element_modificator {}

І таких рядків у нас порядку декількох тисяч. Хочеться замість них відправляти щось менш довге, припустимо:

.b1 {}

Як нам це зробити?
Класи CSS у нас використовуються в кількох місцях: по-перше, у файлі CSS, по-друге, в HTML, і, по-третє, в JavaScript.
Почнемо з CSS-файлу. Перше, що доведеться зробити, — це об'єднати CSS-файлів в один, так як якщо ми займемося заміною в різних файлах, то не зможемо бути впевненими у відсутності конфліктів (технічно скоротити назви можна і без об'єднання в один файл, але необхідний проміжний список замін, який доведеться довантажувати при обробці кожного нового файлу; цей варіант реалізувати складніше і витратніше з точки зору необхідних ресурсів, — прим. ред.). Далі ми пройдемося по отриманому файлику який-небудь програмкою і отримуємо на виході дві речі: файл з заміненими іменами і список замін у вигляді:

{ 'block__element_modificator': 'aBc' }

Поки все просто. Йдемо далі.
Тепер нам потрібно замінити ці класи в HTML. Це вже не так просто: класи можуть збиратися з окремих шматків рядків, змінні в шаблонах можуть бути частиною класів, збирати ім'я класу з цих частин ми можемо не всередині атрибуту class, а де-небудь окремо і т. д. Ну і де-то в нас може на тезі використовуватися один клас, а десь- кілька. Нам потрібно виявити всі ці моменти:

<div class="block__element block__element_{some_variable_name} {some_other_class_from_variable}">

Якщо ми пропустимо хоч одне таке місце, верстка зламається.

Крім цього, назви класів ми використовуємо в JavaScript. Там визначити, що саме у нас є ім'ям класу, ще складніше:

var className = "block__element_modificator";
$elem.addClass(className);

але не правити нічого зайвого:

var block = ...;

Варто зазначити, що клас в JavaScript може зберігатися просто у вигляді змінної, по якій не буде зрозуміло, що це саме клас. Знову ж таки, може використовуватися всяка логіка при побудові імен класів, або ж змінна може називатися як клас, тобто просто регулярним виразом виконати заміну буде не можна.

У підсумку просте завдання — скорочення імен класів — у нас перетворюється у щось нетривіальне.

При всьому цьому стиск імен класів дає нам не дуже великий виграш за розміром. Є ефективніші способи оптимізації розміру стилів — наприклад, очищення від невживаних файлів правил. При використанні бібліотек начебто Bootstrap або иконочных шрифтів начебто Font Awesome в збірку потрапляють сотні невикористовуваних правил. Точно так само вага додають правила пропущені і неочищені при рефакторинге. Якщо б ми могли відправляти в браузер тільки реально використовувані правила, це дало б нам набагато більший виграш в розмірі.

— Прибирати з складання невикористані елементи так само складно? І дійсно цей «історичний хвіст» дає великий приріст до розміру збірки?

— Якщо проект розвивається кілька років, то в ньому можуть зібратися тонни сміття. Причому я зараз говорю не тільки про окремі імена класів, а й про складні селекторах з вкладеністю. Наприклад, правило:

.news .title {}

У нас на сайті можуть використовуватися окремо і клас news, і клас title. При цьому в такій комбінації, як і в правилі, вони можуть ніколи не зустрічатися. У цій ситуації правило теж можна спокійно видалити. В результаті для видалення невикористаного коду нам потрібно зрозуміти структуру сторінки, причому не тільки в поточному стані, а у всіх можливих (сторінка може бути для авторизованого або неавторизованого користувача, з попапом, персональної рекламою або вибіркою записів певного типу в стрічці друзів). Варто врахувати, що для розуміння структури сторінки нам одного HTML не достатньо, оскільки у нас є JavaScript, який вміє все це змінювати. По-хорошому, після того, як ми побудували дерево можливих станів для сторінки, нам потрібно зрозуміти, як саме наш JavaScript може це дерево змінювати.

І ось тільки після того, як ми всі це зрозуміли, ми можемо зі спокійною совістю видаляти правила з CSS.

Те ж саме стосується скорочення JavaScript. Ми можемо в автоматичному режимі видалити невикористовувані змінні і функції. Але код, що стосується роботи з HTML, ми так видаляти не можемо, тому що без знання структури сторінки ми не маємо можливості зрозуміти, що з нього нам правда потрібно, а що ніколи не буде використано.

— А чи не можна просто використовувати якийсь інший підхід при оптимізації?

— Ми можемо спробувати зайти з іншого боку. Наприклад, розбивши загальний бандл CSS і JavaScript на окремі бандли для різних сторінок, щоб користувачеві відправлялася лише те, що потрібно для поточної сторінки. Припустимо, він прийшов на головну сторінку — давайте відправимо йому тільки те, що необхідно для головної, щоб вона здавалася швидше, а решта завантажимо як-небудь потім. Для спрощення ми можемо навіть не по сторінкам складання робити, а станом користувача — для авторизованого або неавторизованого (тобто частина додавати вже після авторизації).

Тільки для того, щоб це зробити швидко, нам знову потрібно знати, на якій сторінці знаходиться, і як HTML, CSS і JavaScript впливають один на одного. Ми, звичайно, можемо це все прописати і руками, але робота ця дуже довга і невдячна.

І це ми поки обговорили лише зменшення розміру файлу в браузер файлів. А також існують проблеми конфліктів імен, розв'язання залежностей, перенесення коду з проекту на проект таким чином, щоб нічого не забути, видалення непотрібного коли з вихідного коду у редакторі та багато інших.

— Невже ніякого інструментарію для рішення цих проблем не існує? Як же вийти з цього «замкненого кола»?

— Спочатку інтерв'ю я як раз говорив, що під фронтенде зараз існує два паралельні світи: світ серверних додатків і світ SPA. У світі SPA багато з описаних вище проблем успішно вирішені, і про них ніхто не згадує, а от у світі серверних додатків вони актуальні і досі.

При цьому ми не можемо просто взяти і почати писати SPA, тому що до цих пір є велика кількість областей, де динаміки на сторінках мало, а індексація пошуковими і доступність з максимального числа пристроїв актуальна: це інтернет-магазини, довідники, урядові сайти з високими вимогами по аксессабилити та інші.

На жаль, просто взяти існуючі інструменти від SPA теж не можна. Вони створювалися під іншу середу з іншими вимогами. Але ось ідеї і підходи, які в цих інструментах використовуються, чудово переносяться і використовуються де завгодно. Саме про цих ідеях, підходах, особливості та проблеми їх застосування у різних середовищах, а також про те, що вже зараз можна використовувати і там, і там, і буде мій доповідь на HolyJS.

— Ідея, начебто, лежить на поверхні. Чому ж вона не йде в маси?

— Ідея ще йде в маси. Є ізоморфні програми і спроби схрестити React з Django і Rails. Є bem-tools, приводом для створення якого було багато проблем, про які я буду розповідати в своїй доповіді. Є спроби подружити HTML і CSS на сервері pstcss-modules, який написав мій колега Саша Мадянкин. Тобто, підходів до проблеми з різних сторін багато, хоча і немає одного загального популярного загальновизнаного рішення.

Одна з головних причин, чому це рішення досі не з'явилося, на мій погляд, полягає в тому, що кількість розробників SPA сильно менше, ніж кількість розробників серверних додатків. І навіть серед останніх тих, хто стикався і працював з усіма тими інструментами і концепціями, про які я буду говорити в доповіді, не дуже багато.

Як раз для того, щоб якомога більше людей дізналося про цих концепціях і початок думати в цих термінах і, сподіваюся, писати інструменти для роботи з ними на сервер, я і готую свою доповідь.

Дякуємо за розмову!

В рамках бесіди ми коротко описали проблеми, з якими щодня стикаються фронтенд-розробники. Про те, як саме підхід «JS» може спростити ситуацію, слухайте у доповіді Олексія Іванова на HolyJS. Крім цього, на конференції буде кілька інших доповідей, пов'язаних з архітектурою веб-додатків. Ну і зрозуміло, нашого сьогоднішнього співрозмовника можна буде там же, не відходячи від каси, задати питання.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.