Динамічне оновлення веб-сторінки

image
Введення
Нікого вже не здивуєш концепцією динамічного HTML, майже всі сайти давно в тій чи іншій мірі використовують javascript для того, щоб зробити сторінки інтерактивними. А з появою технології AJAX стало можливим асинхронно генерувати запити до сервера, щоб змінювати старі дані на сервері або отримувати нові. Але як саме оновлювати структуру сторінки? Хто повинен генерувати новий html — сервер або javascript? А може, все разом?

Подивимося, як можна відповісти на ці питання.

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

Будь-веб-додаток можна логічно поділити на дві складові — клієнтську частину та серверну частину. До клієнтської частини відносяться сам браузер і скрипти, які він виконує, до серверної — набір скриптів, які генерують відповідь на будь-який запит користувача.

Життя будь-сторінки починається з запиту від клієнта до сервера. Відповіддю буде-код сторінки, що містить, крім структури і стилів, логіку клієнтської частини.

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

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

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

Тіло нашої сторінки може виглядати, наприклад, так:

<span id="subscr_cnt">Передплатників: 42</span>
<ul id="news">
<li><a href="/australia">Найбільші на Землі метеоритні кратери випадково знайшли в Австралії</a></li>
<li><a href="/wonderwoman">Диво-жінка відповіла на критику про своїх грудей</a></li>
<li><a href="/romeo_madness">«Ромео і Джульєтту» екранізують в дусі «300 спартанців»</a></li>
</ul>

Варіант 1 — дублювання
Основна ідея — логіку відображення знає і клієнтська і серверна частина. В такому випадку, відповіді на регулярні запити з боку клієнта можуть містити виключно дані — зміни в моделі, і виглядати, наприклад, так:

{
subscr_cnt: 44,
news:[
{
href: "/wiskey",
name: "Названі кращі у світі сорти віскі 2015 року"
},
{
href: "/kindergarden",
name: "У Нью-Йорку з'явився дитячий сад для дорослих"
}
]
}

При отриманні такої відповіді клієнтська частина «обертає» дані в html-теги, додає необхідні тексти і оновлює структуру сторінки.

Сервера ж знання про відображення потрібні тільки для того, щоб згенерувати початкову версію сторінки.

Плюси підходу:
  • Малий обсяг трафіку — передаються тільки необхідні дані;


Мінуси підходу:
  • Потрібно продублювати код — він буде і клієнтської частини, і в серверній;
  • Клієнтська частина повинна знати, як саме чинити з кожною порцією даних від сервера — іноді потрібно замінити html-елемента, іноді додати нові дані до вже існуючого коду;
Варіант 2 — всемогутній сервер і «товсті» відповіді
Основна ідея — логіку відображення знає тільки сервер, клієнт отримує вже готовий html-код елементів. Тут відповідь сервера виглядає так:

{
subscr_cnt: "Передплатників: 44",
news: "<li><a href="/australia\">Найбільші на Землі метеоритні кратери випадково знайшли в Австралії</a></li> \n <li><a href="/wonderwoman\">Диво-жінка відповіла на критику про своїх грудей</a></li> <li><a href="/romeo_madness\">«Ромео і Джульєтту» екранізують в дусі «300 спартанців»</a></li> <li><a href="/wiskey\">Названі кращі у світі сорти віскі 2015 року</a></li> <li><a href="/kindergarden\">У Нью-Йорку з'явився дитячий сад для дорослих</a></li>"
}

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

Плюси підходу:
  • Простота реалізації;
  • Відсутність дублювання коду;


Мінуси підходу:
  • Багаторазова генерація одного і того ж коду, особливо неефективно при невеликих змінах;
  • Величезний обсяг трафіку, особливо на великих сторінках;
Варіант 2а — всемогутній сервер і «тонкі» відповіді
Можна спробувати виправити головний недолік попереднього варіанту. Сервер може не відправляти весь html компонента, а надсилати тільки «дельту» — зміни, які необхідно внести. Наша відповідь тоді може стати таким:

{
subscr_cnt: {
html: "Передплатників: 44",
mode: "replace"
},
news: {
html: "<li><a href="/wiskey\">Названі кращі у світі сорти віскі 2015 року</a></li> <li><a href="/kindergarden\">У Нью-Йорку з'явився дитячий сад для дорослих</a></li>",
mode: "append"
}
}

Тепер клієнт визначає елемент, який буде змінювати, і те, як він його буде змінювати, безпосередньо з відповіді сервера.

Плюси підходу:
  • Відсутність дублювання коду;


Мінуси підходу:
  • Все ще досить великий об'єм мережевого трафіку;
  • Клієнт повинен надіслати серверу поточний стан кожної компоненти, закодоване певним чином, щоб сервер зрозумів, щодо чого вважати дельту;
  • Складність обчислення і записи дельти у разі нетривіальних змін;
  • Загальне ускладнення і клієнтської і серверної частини;
Варіант 3 — всемогутній javascript
Можна перекласти всю відповідальність за генерацію html на клієнта. В такому випадку сервер буде тільки надавати дані, необхідні для відображення. Відповіді, як і в першому варіанті, будуть містити тільки дані:

{
subscr_cnt: 44,
news:[
{
href: "/wiskey",
name: "Названі кращі у світі сорти віскі 2015 року"
},
{
href: "/kindergarden",
name: "У Нью-Йорку з'явився дитячий сад для дорослих"
}
]
}

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

Плюси підходу:
  • Малий обсяг трафіку — передаються тільки необхідні дані;
  • Зменшення навантаження на сервер;


Мінуси підходу:
  • Високе навантаження на комп'ютер користувача;
  • Можлива надмірність — частина знань клієнтської частини про відображення може так і залишитися незатребуваною, якщо якісь події не настануть;


Висновок
Кожен з розглянутих методів має право на життя, і може бути використаний в проектах різної складності. Особисто я зустрінутих мною проектах найчастіше бачив перший варіант, незважаючи на порушення ним мого улюбленого принципу DRY — don't repeat yourself.

А які принципи ви використовуєте при розробці динамічних сторінок?

Джерело: Хабрахабр

0 коментарів

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