使

使用 Vite 在 15 分钟内设置微前端架构!

2025-05-27

使用 Vite 在 15 分钟内设置微前端架构!

在单体式前端架构中,单个代码库负责处理整个用户界面。虽然这可以简化初始开发,但随着应用程序的增长,它会变得复杂:

  • 扩展:在单体仓库中工作的大型团队可能会面临合并冲突、较慢的 CI/CD 管道以及依赖关系困难
  • 独立性:有时处理共享内容可能会影响其他团队
  • 弹性:一次故障可能会导致整个应用程序崩溃

当你开始面临这些问题时,微前端可以帮到你。与 Web 组件不同,Web 组件的跨框架通信受限,并且生命周期管理也面临挑战,而基于 Vite 的微前端允许开发者使用不同的框架。它们提供了灵活的工具、更完善的状态管理和更强大的集成选项。在一个经过多年发展的实际软件中,能够处理多个框架可以让你在需要时顺利地从旧框架迁移到新框架。

在本文中,我们将使用Vite作为构建工具,创建一个微前端环境,并将Vue.jsAngularReact组件整合到统一的体验中。例如,一个模块化新闻门户,每个框架负责处理特定的部分。

模块化新闻门户

这个模块化新闻门户将具有:

  • 使用 Vue.js 制作的Header:带有一个简单的导航栏
  • 使用 React 制作的 Trending显示最后一篇文章
  • 使用 Angular 制作的精彩内容展示最受欢迎的文章

在现实世界的例子中,将新闻管理分散到多种技术中并不是理想的选择,但它很好地服务于我们的例子。

构建 Shell

在微前端架构中,Shell充当微前端的容器。它有 3 个主要特点:

  • 协调:Shell 负责将不同的微前端加载并渲染到应用程序的指定区域
  • 编排:它处理导航、共享样式、共享状态、数据等全局问题……
  • 入口点:这是用户在浏览器中首先加载的内容。如果某个微前端加载失败,它也可以提供回退机制。

我们设置中的 Shell 将使用 Vite 并动态加载 ESM 模块:

host/
├── index.html  # Main entry point
├── main.js     # Loads the micro-frontends
├── vite.config.js
├── package.lock.json
├── package.json
apps/            # Contains individual micro-frontends
├── header/
    ├── src/
        ├── components/
            ├── Header.vue
        ├── main.js
    ├── vite.config.js
    ├── package.lock.json
    ├── package.json
├── trending/
    ├── src/
        ├── components
            ├── Trending.jsx
        ├── main.jsx
    ├── eslint.config.js
    ├── package.lock.json
    ├── vite.config.js
├── highlights/
Enter fullscreen mode Exit fullscreen mode

让我们建造它吧!

我们首先为我们的主机和微前端初始化一个 Vite 工作区。

mkdir news-portal && cd news-portal  
npm init vite@latest host --template vanilla  
Enter fullscreen mode Exit fullscreen mode

让我们组织项目来分离每个微前端:

mkdir -p apps/header apps/trending apps/highlights
Enter fullscreen mode Exit fullscreen mode

现在,让我们使用 DOM 中的组件架构创建简单的 index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>News Portal</title>
</head>
<body>
  <div id="header"></div>
  <div id="trending"></div>
  <div id="highlights"></div>
  <script type="module" src="./src/main.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

现在,让我们创建负责挂载微前端的 main.js 文件(请注意,在我们构建微前端之前,导入不会起作用):

// main.js
import { mount as mountHeader } from '../apps/header/dist/header.js';
import { mount as mountTrending } from '../apps/trending/dist/trending.js';
import { mount as mountHighlights } from '../apps/highlights/dist/highlights.js';

mountHeader(document.querySelector('#header'));
mountTrending(document.querySelector('#trending'));
mountHighlights(document.querySelector('#highlights'));
Enter fullscreen mode Exit fullscreen mode

然后,我们在 vite.config.js 中创建 Vite 配置以启用 Vite 服务器:

// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  server: {
    port: 3000,
    open: true,
  },
});
Enter fullscreen mode Exit fullscreen mode

启动 Shell 以准备服务:

cd host
npm install
npm run dev
Enter fullscreen mode Exit fullscreen mode

现在,我们已经成功创建了 Shell,它已经准备好为我们未来的微前端提供服务了。现在,让我们开始创建它们吧!

使用 Vue 3 构建标题

让我们在应用程序中创建Header文件夹并导航到其中:

cd apps
npm init vite@latest header --template vue  
cd header  
npm install  
Enter fullscreen mode Exit fullscreen mode

在里面src/components/Header.vue,创建一个带有导航和搜索栏的简单标题:

<template>
  <header class="header">
    <nav>
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">World</a></li>
        <li><a href="#">Tech</a></li>
        <li><a href="#">Sports</a></li>
      </ul>
    </nav>
    <input type="text" placeholder="Search news..." />
  </header>
</template>

<script>
export default {
  name: 'Header',
};
</script>

<style scoped>
.header {
  display: flex;
  justify-content: space-between;
  padding: 1em;
  background: #333;
  color: white;
}
nav ul {
  display: flex;
  list-style: none;
}
nav ul li {
  margin-right: 1em;
}
input {
  padding: 0.5em;
}
</style>
Enter fullscreen mode Exit fullscreen mode

我们需要一个src/main.js来安装组件:

import { createApp } from 'vue';
import Header from './components/Header.vue';

export function mount(el) {
  createApp(Header).mount(el);
}
Enter fullscreen mode Exit fullscreen mode

配置 vite.config.js 以将此应用程序公开为库:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    lib: {
      entry: './src/main.js',
      name: 'Header',
      fileName: 'header',
    },
  },
})
Enter fullscreen mode Exit fullscreen mode

最后,构建微前端以生成 dist 文件夹:

cd apps/header
npm run build 
Enter fullscreen mode Exit fullscreen mode

现在你应该能够在Shell中看到Header的服务了。这是因为我们告诉 Shell 要使用 Header 的 dist 文件夹,并且我们用命令生成了它。npm build

使用 React 18 构建趋势部分

让我们在应用程序内创建Trending文件夹并导航到其中:

cd apps
npm init vite@latest trending --template react  
cd trending
npm install  
Enter fullscreen mode Exit fullscreen mode

添加趋势组件src/components/Trending.jsx

import React from 'react';

const Trending = () => {
  const articles = [
    { id: 1, title: "React 18 Released", summary: "Learn what's new in React 18." },
    { id: 2, title: "AI Revolution", summary: "How AI is transforming industries." },
  ];

  return (
    <section className="trending">
      <h2>Trending News</h2>
      <ul>
        {articles.map((article) => (
          <li key={article.id}>
            <h3>{article.title}</h3>
            <p>{article.summary}</p>
          </li>
        ))}
      </ul>
    </section>
  );
};

export default Trending;
Enter fullscreen mode Exit fullscreen mode

我们需要一个src/main.jsx来安装组件:

import React from 'react';
import ReactDOM from 'react-dom/client'; 
import Trending from './components/Trending';

export function mount(el) {
  const root = ReactDOM.createRoot(el); 
  root.render(<Trending />); 
}
Enter fullscreen mode Exit fullscreen mode

配置vite.config.js

import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    lib: {
      entry: './src/main.jsx',
      name: 'Trending',
      fileName: 'trending',
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

构建以生成 dist 文件夹:

npm run build
Enter fullscreen mode Exit fullscreen mode

好了!现在,我们的 Shell 内部、Header 下已经有了第二个微前端。

使用 Angular 19 构建亮点

补充:如果没有模块联合、自定义元素或小部件,我暂时无法让 Vite 与 Angular 19 兼容。我目前正在尝试在这三者之间寻找最佳方案,以便在本文后续的编辑中向您推荐最高效的方案。


奖励:与 Vite 的运行时联合

虽然上述方法侧重于在构建步骤中组合微前端,但对于生产环境,您可能需要采用运行时联合。这种方法为微前端提供了真正的独立性,允许每个模块单独部署和更新。

每个微前端都可以托管在自己的服务器或域上。例如:

Shell应用程序中的动态加载

Shell 应用程序在运行时使用 import() 或类似方法动态加载微前端。以下是 Shell 如何从 Shell 中微前端清单 json 文档中列出的相应 URL 动态加载 Header 和 Trending 模块main.js

微服务清单(例如: https: //news-portal.com/microfrontends.json):

[
  {
    "name": "Header",
    "url": "https://header.news-portal.com/dist/header.js"
  },
  {
    "name": "Trending",
    "url": "https://trending.news-portal.com/dist/trending.js"
  }
]
Enter fullscreen mode Exit fullscreen mode

main.js

export default {
  data() {
    return {
      modules: [],
    };
  },
  async mounted() {
    try {
      const response = await fetch('https://news-portal.com/microfrontends.json');
      const microfrontends = await response.json();

      for (const mfe of microfrontends) {
        const module = await import(mfe.url);
        this.modules.push({
          name: mfe.name,
          component: module.default,
        });
      }
    } catch (error) {
      console.error('Failed to load microfrontends:', error);
    }
  },
  template: `
    <div>
      <h1>Shell App</h1>
      <div v-for="module in modules" :key="module.name">
        <component :is="module.component" />
      </div>
    </div>
  `,
};
Enter fullscreen mode Exit fullscreen mode

共享依赖项

为了避免重复使用 Vue 等常见依赖项,我们可以在 Vite 构建过程中使用peerDependenciespackage.json外部化它们。我们可以在 中进行配置vite.config.js

import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    rollupOptions: {
      external: ['vue'], // Prevent bundling Vue with the module
    },
  },
});

Enter fullscreen mode Exit fullscreen mode

这确保Shell提供依赖项(例如 Vue),并且HeaderTrending模块都依赖于同一个实例。

运行时联合的好处

  • 独立部署:每个模块都可以更新,而无需重新部署整个应用程序。
  • 可扩展性:团队可以自主地在不同的微前端上工作。
  • 动态组合:无需触及 shell 或其他微前端即可添加或更新新模块。

常见的陷阱

端口冲突

  • 在 vite.config.js 或 angular.json 中为每个微前端分配一个唯一的端口以避免冲突

共享库

  • 对常用库使用共享 CDN,以减少重复和捆绑包大小
  • 确保版本兼容性以避免运行时错误

CORS问题

在本地开发过程中,由于浏览器安全策略的原因,托管在不同端口上的微前端可能会面临 CORS 问题

对于生产环境,请配置您的 Web 服务器以允许跨源请求:

add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept';
Enter fullscreen mode Exit fullscreen mode

通过将所有微前端和 Shell 部署在同一域或子域结构下(例如,https://news-portal.com/header、https : //news-portal.com/trending),最大限度地减少 CORS 要求。

Github链接

Github 代码:代码库

结论

恭喜,您已经使用 Vite 搭建了第一个 MicroFrontend 架构。对于之前使用过 Web Components 的用户,您可能会发现它更加简单易用。希望它能够在您需要解耦软件多个前端开发时,帮助您搭建第一个 MFE 项目。

文章来源:https://dev.to/onepoint/setup-a-micro-frontend-architecture-in-15min-with-vite-4pbg
PREV
用户体验的极简主义艺术
NEXT
使用 Terraform 模块掌握基础设施即代码:实用指南