\n \n \n
\n \n \n \n\n```\n\n### Жизненный цикл микроприложения\n\n```javascript\n// Каждое микроприложение имеет жизненный цикл\n\n// dashboard.js (одно из микроприложений)\nexport async function bootstrap() {\n // Инициализация приложения\n console.log('Dashboard bootstrapping');\n}\n\nexport async function mount() {\n // Монтирование приложения в DOM\n const container = document.getElementById('main-app');\n console.log('Dashboard mounting');\n \n // Рендеруем приложение (например, React, Vue, Angular)\n ReactDOM.render(\n ,\n container\n );\n}\n\nexport async function unmount() {\n // Удаление приложения из DOM\n console.log('Dashboard unmounting');\n ReactDOM.unmountComponentAtNode(\n document.getElementById('main-app')\n );\n}\n```\n\n### Практический пример архитектуры\n\n```\n┌─────────────────────────────────────────────┐\n│ Shell Application (Main App) │\n│ (управляет маршрутизацией и т.д.) │\n└─────────────────────────────────────────────┘\n ↓\n┌──────────────┬──────────────┬──────────────┐\n│ Header │ Dashboard │ Settings │\n│ Micro App │ Micro App │ Micro App │\n│ (React 19) │ (Vue 3) │ (Angular) │\n│ Port: 3001 │ Port: 3002 │ Port: 3003 │\n└──────────────┴──────────────┴──────────────┘\n```\n\nКаждое микроприложение:\n- Может быть написано на разных фреймворках\n- Разрабатывается независимо\n- Имеет свой build процесс\n- Деплоится независимо\n\n### Преимущества Single SPA\n\n**1. Независимость команд**\n\n```javascript\n// Команда A разрабатывает Dashboard\n// Команда B разрабатывает Settings\n// Они работают полностью независимо\n\n// dashboard/package.json\n{\n \"name\": \"@org/dashboard\",\n \"version\": \"1.2.3\",\n \"dependencies\": {\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\"\n }\n}\n\n// settings/package.json\n{\n \"name\": \"@org/settings\",\n \"version\": \"2.1.0\",\n \"dependencies\": {\n \"vue\": \"^3.0.0\" // Другой фреймворк!\n }\n}\n```\n\n**2. Независимое деплоирование**\n\n```bash\n# Обновляем только Dashboard\nnpm run build\naws s3 cp dist s3://my-bucket/dashboard/ --recursive\n\n# Settings остается неизменным\n# Header остается неизменным\n```\n\n**3. Общие зависимости**\n\n```javascript\n// shared-dependencies.js\nconst system = {\n react: 'https://cdn.jsdelivr.net/npm/react@19/dist/react.production.min.js',\n 'react-dom': 'https://cdn.jsdelivr.net/npm/react-dom@19/dist/react-dom.production.min.js',\n lodash: 'https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js'\n};\n\n// Все микроприложения используют одну версию React\n// Экономия трафика и памяти\n```\n\n### Практический пример с Webpack Module Federation\n\n```javascript\n// Shell App (Webpack config)\n// webpack.config.js\nconst ModuleFederation = require(\"@webpack-cli/serve/dist/utils/ModuleFederationPlugin\");\n\nmodule.exports = {\n plugins: [\n new ModuleFederation({\n name: \"shell\",\n shared: {\n react: { singleton: true },\n \"react-dom\": { singleton: true }\n },\n remotes: {\n dashboard: \"dashboard@http://localhost:3002/remoteEntry.js\",\n settings: \"settings@http://localhost:3003/remoteEntry.js\"\n }\n })\n ]\n};\n\n// Dashboard Micro App (Webpack config)\nmodule.exports = {\n plugins: [\n new ModuleFederation({\n name: \"dashboard\",\n filename: \"remoteEntry.js\",\n exposes: {\n \"./App\": \"./src/App\"\n },\n shared: {\n react: { singleton: true },\n \"react-dom\": { singleton: true }\n }\n })\n ]\n};\n```\n\n### Когда использовать Single SPA\n\n**Хорошо подходит когда:**\n- Большое приложение с многими независимыми модулями\n- Разные команды разрабатывают разные части\n- Нужна возможность независимого деплоя\n- Нужна гибкость в выборе фреймворка для разных частей\n- Требуется масштабируемость\n\n**Не подходит когда:**\n- Маленький проект\n- Простое приложение\n- Кроссбраузерность критична (IE11)\n- Повышенная сложность нежелательна\n\n### Вызовы и решения\n\n**Проблема 1: Управление состоянием**\n\n```javascript\n// Необходимо делиться состоянием между микроприложениями\n// Решение: Global Store\n\nconst globalStore = {\n user: null,\n notifications: [],\n setUser(user) { this.user = user; },\n addNotification(notification) { this.notifications.push(notification); }\n};\n\n// Каждое микроприложение может использовать globalStore\n```\n\n**Проблема 2: Конфликты версий библиотек**\n\n```javascript\n// Решение: Singleton shared dependencies\nshared: {\n react: {\n singleton: true,\n strictVersion: false,\n requiredVersion: \"^19.0.0\"\n }\n}\n```\n\n**Проблема 3: Ошибки в одном приложении могут сломать всё**\n\n```javascript\n// Решение: Error boundaries и изоляция ошибок\nsingleSpa.addErrorHandler((error) => {\n if (error.type === 'mount') {\n console.error('Error mounting app:', error);\n // Не позволяем ошибке распространяться\n }\n});\n```\n\n### Примеры использования в производстве\n\n- **Spotify:** Использует похожий подход для своего веб-приложения\n- **Google Cloud Console:** Масштабное приложение с микрофронтендами\n- **Slack:** Независимые модули приложения\n\nSingle SPA — это мощный паттерн для организации больших фронтенд приложений, позволяющий масштабировать разработку и давая свободу независимым командам разработчиков.","dateCreated":"2026-03-22T10:06:55.778087","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Что такое Single SPA?

1.0 Junior🔥 161 комментариев
#JavaScript Core#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Single SPA — Single Page Application Architecture

Single SPA (Single Page Application) — это архитектурный паттерн и JavaScript библиотека, которая позволяет создавать микрофронтенды и управлять множеством независимых приложений внутри одного браузера. Это решение для масштабирования больших фронтенд проектов.

Основная идея

Вместо одного монолитного приложения, приложение разделяется на несколько независимых микроприложений (micro-apps), которые:

  • Загружаются динамически
  • Работают независимо
  • Имеют свои зависимости
  • Могут разрабатываться разными командами
  • Могут обновляться независимо друг от друга

Как это работает

// 1. Главное приложение (Shell Application)
// index.html
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/single-spa@5/dist/system/single-spa.js"></script>
  </head>
  <body>
    <main id="main-app"></main>
    
    <script>
      // Регистрируем микроприложения
      
      // 1. Приложение "header"
      singleSpa.registerApplication({
        name: '@org/header',
        app: () => System.import('@org/header'),
        activeWhen: '/', // Всегда активна
      });
      
      // 2. Приложение "dashboard"
      singleSpa.registerApplication({
        name: '@org/dashboard',
        app: () => System.import('@org/dashboard'),
        activeWhen: '/dashboard',
      });
      
      // 3. Приложение "settings"
      singleSpa.registerApplication({
        name: '@org/settings',
        app: () => System.import('@org/settings'),
        activeWhen: '/settings',
      });
      
      // Запускаем Single SPA
      singleSpa.start();
    </script>
  </body>
</html>

Жизненный цикл микроприложения

// Каждое микроприложение имеет жизненный цикл

// dashboard.js (одно из микроприложений)
export async function bootstrap() {
  // Инициализация приложения
  console.log('Dashboard bootstrapping');
}

export async function mount() {
  // Монтирование приложения в DOM
  const container = document.getElementById('main-app');
  console.log('Dashboard mounting');
  
  // Рендеруем приложение (например, React, Vue, Angular)
  ReactDOM.render(
    <Dashboard />,
    container
  );
}

export async function unmount() {
  // Удаление приложения из DOM
  console.log('Dashboard unmounting');
  ReactDOM.unmountComponentAtNode(
    document.getElementById('main-app')
  );
}

Практический пример архитектуры

┌─────────────────────────────────────────────┐
│        Shell Application (Main App)         │
│    (управляет маршрутизацией и т.д.)       │
└─────────────────────────────────────────────┘
                        ↓
┌──────────────┬──────────────┬──────────────┐
│   Header     │  Dashboard   │  Settings    │
│   Micro App  │  Micro App   │  Micro App   │
│ (React 19)   │ (Vue 3)      │ (Angular)    │
│ Port: 3001   │ Port: 3002   │ Port: 3003   │
└──────────────┴──────────────┴──────────────┘

Каждое микроприложение:

  • Может быть написано на разных фреймворках
  • Разрабатывается независимо
  • Имеет свой build процесс
  • Деплоится независимо

Преимущества Single SPA

1. Независимость команд

// Команда A разрабатывает Dashboard
// Команда B разрабатывает Settings
// Они работают полностью независимо

// dashboard/package.json
{
  "name": "@org/dashboard",
  "version": "1.2.3",
  "dependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  }
}

// settings/package.json
{
  "name": "@org/settings",
  "version": "2.1.0",
  "dependencies": {
    "vue": "^3.0.0" // Другой фреймворк!
  }
}

2. Независимое деплоирование

# Обновляем только Dashboard
npm run build
aws s3 cp dist s3://my-bucket/dashboard/ --recursive

# Settings остается неизменным
# Header остается неизменным

3. Общие зависимости

// shared-dependencies.js
const system = {
  react: 'https://cdn.jsdelivr.net/npm/react@19/dist/react.production.min.js',
  'react-dom': 'https://cdn.jsdelivr.net/npm/react-dom@19/dist/react-dom.production.min.js',
  lodash: 'https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js'
};

// Все микроприложения используют одну версию React
// Экономия трафика и памяти

Практический пример с Webpack Module Federation

// Shell App (Webpack config)
// webpack.config.js
const ModuleFederation = require("@webpack-cli/serve/dist/utils/ModuleFederationPlugin");

module.exports = {
  plugins: [
    new ModuleFederation({
      name: "shell",
      shared: {
        react: { singleton: true },
        "react-dom": { singleton: true }
      },
      remotes: {
        dashboard: "dashboard@http://localhost:3002/remoteEntry.js",
        settings: "settings@http://localhost:3003/remoteEntry.js"
      }
    })
  ]
};

// Dashboard Micro App (Webpack config)
module.exports = {
  plugins: [
    new ModuleFederation({
      name: "dashboard",
      filename: "remoteEntry.js",
      exposes: {
        "./App": "./src/App"
      },
      shared: {
        react: { singleton: true },
        "react-dom": { singleton: true }
      }
    })
  ]
};

Когда использовать Single SPA

Хорошо подходит когда:

  • Большое приложение с многими независимыми модулями
  • Разные команды разрабатывают разные части
  • Нужна возможность независимого деплоя
  • Нужна гибкость в выборе фреймворка для разных частей
  • Требуется масштабируемость

Не подходит когда:

  • Маленький проект
  • Простое приложение
  • Кроссбраузерность критична (IE11)
  • Повышенная сложность нежелательна

Вызовы и решения

Проблема 1: Управление состоянием

// Необходимо делиться состоянием между микроприложениями
// Решение: Global Store

const globalStore = {
  user: null,
  notifications: [],
  setUser(user) { this.user = user; },
  addNotification(notification) { this.notifications.push(notification); }
};

// Каждое микроприложение может использовать globalStore

Проблема 2: Конфликты версий библиотек

// Решение: Singleton shared dependencies
shared: {
  react: {
    singleton: true,
    strictVersion: false,
    requiredVersion: "^19.0.0"
  }
}

Проблема 3: Ошибки в одном приложении могут сломать всё

// Решение: Error boundaries и изоляция ошибок
singleSpa.addErrorHandler((error) => {
  if (error.type === 'mount') {
    console.error('Error mounting app:', error);
    // Не позволяем ошибке распространяться
  }
});

Примеры использования в производстве

  • Spotify: Использует похожий подход для своего веб-приложения
  • Google Cloud Console: Масштабное приложение с микрофронтендами
  • Slack: Независимые модули приложения

Single SPA — это мощный паттерн для организации больших фронтенд приложений, позволяющий масштабировать разработку и давая свободу независимым командам разработчиков.