SPA (Single Page Application) — это веб-приложение, которое загружает одну HTML-страницу и динамически обновляет контент без перезагрузки страницы:
// Пример простого SPA роутера
const routes = {
'/': () => showHome(),
'/about': () => showAbout(),
'/contact': () => showContact()
};
function navigate(path) {
history.pushState(null, null, path);
routes[path]();
}SPA — это как настольная программа в браузере! Вместо загрузки новых страниц, приложение динамически меняет содержимое одной страницы. 🖥️
// Традиционное приложение
window.location.href = '/new-page'; // Перезагрузка
// SPA приложение
history.pushState({}, '', '/new-page'); // Без перезагрузки
updateContent(); // Обновление контентаОсновные компоненты SPA приложения:
// Роутер
class Router {
constructor() {
this.routes = {};
window.addEventListener('popstate', this.handleRoute.bind(this));
}
addRoute(path, handler) {
this.routes[path] = handler;
}
navigate(path) {
history.pushState({}, '', path);
this.handleRoute();
}
}
// Компоненты
class Component {
render() {
return '<div>Component content</div>';
}
}Навигация без перезагрузки страницы:
// React Router пример
import { BrowserRouter, Route, Switch } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Switch>
</BrowserRouter>
);
}Данные хранятся в памяти браузера:
// Простое состояние
const state = {
user: null,
posts: [],
currentPage: 'home'
};
// Redux пример
const store = createStore(reducer);
function updateUser(user) {
store.dispatch({ type: 'SET_USER', payload: user });
}Загрузка данных без перезагрузки:
// Fetch API
async function loadData() {
const response = await fetch('/api/data');
const data = await response.json();
updateUI(data);
}
// Axios пример
axios.get('/api/users')
.then(response => {
setUsers(response.data);
});function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}<template>
<div>
<h1>Count: {{ count }}</h1>
<button @click="increment">Increment</button>
</div>
</template>
<script>
export default {
data() {
return { count: 0 };
},
methods: {
increment() {
this.count++;
}
}
};
</script>@Component({
selector: 'app-counter',
template: `
<h1>Count: {{ count }}</h1>
<button (click)="increment()">Increment</button>
`
})
export class CounterComponent {
count = 0;
increment() {
this.count++;
}
}// Быстрая навигация
function showPage(pageId) {
// Скрыть все страницы
document.querySelectorAll('.page').forEach(page => {
page.style.display = 'none';
});
// Показать нужную
document.getElementById(pageId).style.display = 'block';
}// Ленивая загрузка компонентов
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}// Next.js пример
export async function getServerSideProps() {
const data = await fetchData();
return { props: { data } };
}// Предзагрузка критических ресурсов
const link = document.createElement('link');
link.rel = 'preload';
link.href = '/critical-component.js';
link.as = 'script';
document.head.appendChild(link);| SPA | MPA |
|---|---|
| Одна HTML страница | Множество HTML страниц |
| Клиентский роутинг | Серверный роутинг |
| Быстрая навигация | Перезагрузка страниц |
| Сложное SEO | Простое SEO |
| Большой начальный bundle | Маленькие страницы |
✅ Подходит для:
❌ Не подходит для:
// Обработка ошибок
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error('Network error');
return await response.json();
} catch (error) {
showErrorMessage('Failed to load data');
return null;
}
}// Service Worker для офлайн работы
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});// Модульная архитектура
const HeaderApp = () => import('./header-app');
const MainApp = () => import('./main-app');
const FooterApp = () => import('./footer-app');SPA — мощная архитектура для создания интерактивных веб-приложений:
Выбирайте SPA для интерактивных приложений с частыми переходами! 🎯