текст перекладу
Фото Josh Sorenson: https://www.pexels.com/photo/black-flat-screen-computer-monitor-1714208/
Управління станом.
Ці два слова можуть викликати страх навіть у найбільш досвідчених інженерів. Кілька тижнів тому наша команда стикнулася з особливо складною проблемою управління станом під час роботи з застарілим кодом, який містив серверно-рендерений додаток на Handlebars.
Місія? Зберегти синхронізований стан додатка між сервером, де рендеряться шаблони, та клієнтом, де користувачі взаємодіють з додатком.
Це не була типова ситуація для управління станом на клієнтській стороні. Нам потрібне було рішення, яке б легко зв'язувало сервер і клієнт, забезпечуючи ініціалізацію стану на сервері, передачу його в шаблони і потім «магічну» доступність на клієнті без важких маніпуляцій.
Стан нашої боротьби
Традиційні бібліотеки для управління станом на клієнтській стороні виглядали як надмірне рішення, вводили непотрібну складність і не вирішували унікальні проблеми ініціалізації стану на сервері та повторної гідратації на клієнті.
Ми експериментували з різними обхідними шляхами:
- Передача стану як JSON: Ми спробували вставити стан як JSON-об'єкт у HTML, але це швидко стало громіздким і важким для підтримки.
- Повторна гідратація на клієнті: Отримання даних стану повторно на клієнті після початкового рендеру призводило до зайвих мережевих запитів та вузьких місць у продуктивності.
- Інші рішення для управління станом: Ми досліджували повноцінні бібліотеки для управління станом на клієнтській стороні, але вони не зовсім підходили для нашого унікального випадку.
Pico State на допомогу
Розчаровані обмеженнями існуючих рішень, я вирішив створити Pico State, легку бібліотеку для управління станом, спеціально розроблену для серверно-рендерених додатків. Pico State була створена з трьома основними принципами:
- Простота: Інтуїтивно зрозумілий API, який легко освоїти і використовувати, мінімізуючи обсяг шаблонного коду.
- Ізоморфність: Легко використовувана як на сервері, так і на клієнті.
- Легкість: Мінімальний обсяг з нульовими зовнішніми залежностями, що забезпечує оптимальну продуктивність.
Як ми з'єднали сервер і клієнт
Магія Pico State полягає в її здатності створювати спільний об'єкт стану, доступний як на сервері, так і на клієнті. Ось як ми інтегрували його в наш додаток на Handlebars:
- Ініціалізація на сервері (
src/store/index.js
)
const { Store } = require('@uche-exe/pico-state');
// Інтелектуальна гідратація: перевірка наявності стану в localStorage або window
let existingState = JSON.parse(localStorage.getItem("appState")) ?? window.storeInstance?.state;
let store;
if (existingState) {
// Гідратуємо магазин з існуючим станом
store = new Store({ initialState: existingState });
} else {
// Створюємо новий екземпляр магазину
store = new Store();
// Розрізаємо та обробляємо: ініціалізуємо слайси для різних доменів додатку (auth, post, cart)
// з можливими початковими значеннями
const { auth } = store.createSlice({
name: "auth",
initialState: [
{ username: "uche" },
{ fullName: "Uchechukwu Samuel Ottah" },
{ imageUrl: "my_img_url" }
]
});
const { post } = store.createSlice({
name: "post",
});
const { cart } = store.createSlice({
name: "cart",
initialState: {
cartItems: [
// ... початкові елементи корзини
]
}
});
}
// Доступ до екземпляру магазину з боку клієнта, прикріплюючи його до об'єкта "window"
if (typeof window !== "undefined") {
console.log("Ініціалізація магазину на об'єкті window...");
window.storeInstance = store;
}
module.exports = { store };
текст перекладу
**Webpack пакування (**`webpack.config.js`**)**
Щоб зробити наш `store` доступним у браузерах, ми використовуємо Webpack для пакування файлу `store/index.js`, який відповідає за ініціалізацію стану та створення слайсів. Цей процес забезпечує сумісність з браузерами, оскільки як Pico State, так і наш додаток на Handlebars є модулями [_CommonJS_](https://nodejs.org/api/modules.html#modules-commonjs-modules) (тому ми використовуємо синтаксис ‘require’).
module.exports = {
entry: './src/store/index.js',
output: {
filename: 'store.bundle.js',
path: path.resolve(__dirname, 'public/js'),
},
};
```
Ця конфігурація вказує Webpack взяти store/index.js
як точку входу, упакувати його разом із залежностями та вивести результат як store.bundle.js
у директорії public/js
. Цей упакований файл потім включається в наш HTML, щоб зробити store доступним на клієнтській стороні.
- Взаємодія на клієнтській стороні (
public/js/store.js
)
Тут міститься логіка клієнтської частини для взаємодії з нашим store
. Ми використовували jQuery для доступу до storeInstance
, який був відкритий на об'єкті window
, і виконували дії, наприклад, оновлюючи інтерфейс користувача на основі стану.
$(document).ready(async function () {
const store = window.storeInstance;
if (!store) {
console.error("Екземпляр store не знайдено. Перевірте ініціалізацію.");
return;
}
// Динамічний підрахунок товарів у корзині: Оновлюємо кількість товарів у корзині на основі store.state.cart
async function updateCartCount() {
const cartItems = store.state.cart?.cartItems ?? [];
$(".cart-count").text(cartItems.length);
}
// Ініціалізуємо кількість товарів у корзині при завантаженні сторінки
await updateCartCount();
// ... інші функції jQuery для взаємодії з store та оновлення інтерфейсу користувача ...
});
- Інтеграція на клієнтській стороні (
_shared_global_component.hbs
)
Нарешті, ми можемо імпортувати необхідні скрипти, щоб зробити наш state
та логіку маніпуляцій з клієнтської частини доступними в браузері. Ми імпортуємо їх лише одного разу, в одному спільному частковому компоненті (щоб уникнути множинних імпортів, що можуть викликати кілька виконань події).
Результати
Інтеграція Pico State в наш додаток на Handlebars принесла значні переваги:
- Легкість управління станом: Команда могла зосередитись на розробці функцій, замість того, щоб боротися з складнощами синхронізації стану.
- Неймовірна продуктивність: Вилучення зайвих запитів на клієнтській стороні призвело до помітного покращення часу початкового завантаження.
- Краща організація коду: Централізоване управління станом призвело до чистішого та більш підтримуваного коду.
- Підвищена продуктивність розробників: Спрощений підхід до управління станом дозволив команді зосередитись на наданні цінності нашим користувачам.
Кінець саги
Pico State став героєм у нашій сазі управління станом. Його простота, ізоморфність і легка конструкція зробили його ідеальним рішенням для нашого серверно-рендереного додатку на Handlebars. Легко з'єднуючи сервер і клієнт, Pico State дозволив нам створити більш ефективний, підтримуваний і продуктивний додаток.
Якщо ви стикаєтеся з проблемами управління станом у подібному середовищі, раджу вам спробувати Pico State. Це може бути той самий герой, який потрібен вашому проекту.
Якщо вам подобається pico-state і ви хочете зробити його кращим, ви можете просто зайти на сторінку github і створити issue або відкрити PR.
Внесок вітається.
Github: https://github.com/uche-exe/pico-state
NPM: https://www.npmjs.com/package/@uche-exe/pico-state
https://tenor.com: Skeletor Running Away
До наступного разу!
Перекладено з: A tale of Handlebars and State Management