Hyperapp — это минималистичный JavaScript-фреймворк для создания реактивных пользовательских интерфейсов. Его архитектура строится вокруг трёх основных концепций: state, actions и view.
Пример базовой структуры:
import { h, app } from "hyperapp";
const state = {
count: 0
};
const actions = {
increment: () => state => ({ count: state.count + 1 }),
decrement: () => state => ({ count: state.count - 1 })
};
const view = (state, actions) => (
h("div", {}, [
h("h1", {}, state.count),
h("button", { onclick: actions.increment }, "Увеличить"),
h("button", { onclick: actions.decrement }, "Уменьшить")
])
);
app({ init: state, view, actions, node: document.getElementById("app") });
Progressive Web Apps (PWA) — это веб-приложения с функциональностью, схожей с нативными мобильными приложениями, включая offline-доступ, push-уведомления и установку на рабочий стол. Hyperapp легко интегрируется с PWA благодаря своей лёгкости и модульной архитектуре.
Service Worker — ключевой элемент PWA. Он перехватывает сетевые запросы и обеспечивает кеширование ресурсов для офлайн-режима. В Hyperapp его можно подключить следующим образом:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(reg => console.log('Service Worker зарегистрирован:', reg.scope))
.catch(err => console.error('Ошибка регистрации Service Worker:', err));
});
}
В файле service-worker.js можно реализовать кеширование
статических ресурсов:
const CACHE_NAME = 'hyperapp-pwa-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/main.js',
'/styles.css'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME).then(cache => cache.addAll(urlsToCache))
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => response || fetch(event.request))
);
});
Для PWA важно сохранять состояние приложения между сессиями. В Hyperapp это можно реализовать через localStorage или IndexedDB:
const loadState = () => JSON.parse(localStorage.getItem('appState')) || { count: 0 };
const saveState = state => {
localStorage.setItem('appState', JSON.stringify(state));
};
const state = loadState();
const actions = {
increment: () => state => {
const newState = { count: state.count + 1 };
saveState(newState);
return newState;
}
};
Такой подход обеспечивает постоянство данных, даже если пользователь закрывает браузер или теряет интернет-соединение.
PWA часто требуют взаимодействия с внешними API для загрузки данных.
В Hyperapp асинхронные действия реализуются через возвращение функции с
dispatch:
const actions = {
fetchData: () => async (state, actions) => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return { ...state, data };
}
};
Можно комбинировать офлайн-режим и API-запросы, сначала отдавая кешированные данные, а затем обновляя их из сети:
const actions = {
fetchData: () => async (state) => {
const cached = JSON.parse(localStorage.getItem('data'));
if (cached) return { ...state, data: cached };
const response = await fetch('https://api.example.com/data');
const data = await response.json();
localStorage.setItem('data', JSON.stringify(data));
return { ...state, data };
}
};
Для добавления возможности установки PWA на устройство необходимо
обработать событие beforeinstallprompt:
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
document.getElementById('install-btn').style.display = 'block';
});
document.getElementById('install-btn').addEventListener('click', async () => {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
console.log('Установка приложения:', outcome);
deferredPrompt = null;
});
Push-уведомления на клиенте можно реализовать через Push API и Service Worker:
navigator.serviceWorker.ready.then(registration => {
registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: '<ключ>' })
.then(subscription => console.log('Подписка на пуш уведомления:', subscription));
});
Структура проекта может выглядеть следующим образом:
/public
index.html
service-worker.js
/src
app.js
state.js
actions.js
view.js
components/
Header.js
Footer.js
Counter.js
/package.json
state.js — глобальный state приложения.actions.js — все действия, включая асинхронные и
побочные эффекты.view.js — корневой компонент интерфейса.components/ — переиспользуемые UI-компоненты.Hyperapp позволяет легко масштабировать проект, добавлять модули и интегрировать PWA-функции без излишней сложности.