前端微前端:别让你的应用变成巨石应用

前端微前端:别让你的应用变成巨石应用

毒舌时刻

这应用做得跟巨石似的,想改个功能都得动全身。

各位前端同行,咱们今天聊聊前端微前端。别告诉我你还在维护一个巨大的单体应用,那感觉就像在没有分区的大房子里生活——能住,但乱得要命。

为什么你需要微前端

最近看到一个项目,代码量超过 100 万行,构建时间超过 10 分钟,团队协作困难。我就想问:你是在做应用还是在做代码仓库?

反面教材

// 反面教材:单体应用 // App.jsx import React from 'react'; import Header from './components/Header'; import Sidebar from './components/Sidebar'; import Dashboard from './components/Dashboard'; import Users from './components/Users'; import Products from './components/Products'; import Orders from './components/Orders'; import Settings from './components/Settings'; function App() { return ( <div> <Header /> <div> <Sidebar /> <main> <Dashboard /> <Users /> <Products /> <Orders /> <Settings /> </main> </div> </div> ); } export default App; 

毒舌点评:这代码,就像把所有东西都塞进一个大袋子里,管它有用没用。

正确姿势

1. Module Federation

// 正确姿势:Module Federation // 1. 安装依赖 // npm install webpack@5 // 2. 配置 webpack // webpack.config.js const { ModuleFederationPlugin } = require('webpack').container; module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'host', remotes: { dashboard: 'dashboard@http://localhost:3001/remoteEntry.js', users: 'users@http://localhost:3002/remoteEntry.js', products: 'products@http://localhost:3003/remoteEntry.js', orders: 'orders@http://localhost:3004/remoteEntry.js', settings: 'settings@http://localhost:3005/remoteEntry.js', }, shared: { react: { singleton: true, requiredVersion: '^18.2.0', }, 'react-dom': { singleton: true, requiredVersion: '^18.2.0', }, }, }), ], }; // 3. 远程应用配置 // dashboard/webpack.config.js const { ModuleFederationPlugin } = require('webpack').container; module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'dashboard', filename: 'remoteEntry.js', exposes: { './Dashboard': './src/Dashboard', }, shared: { react: { singleton: true, requiredVersion: '^18.2.0', }, 'react-dom': { singleton: true, requiredVersion: '^18.2.0', }, }, }), ], }; // 4. 主机应用 // App.jsx import React, { lazy, Suspense } from 'react'; import Header from './components/Header'; import Sidebar from './components/Sidebar'; const Dashboard = lazy(() => import('dashboard/Dashboard')); const Users = lazy(() => import('users/Users')); const Products = lazy(() => import('products/Products')); const Orders = lazy(() => import('orders/Orders')); const Settings = lazy(() => import('settings/Settings')); function App() { return ( <div> <Header /> <div> <Sidebar /> <main> <Suspense fallback={<div>加载中...</div>}> <Dashboard /> <Users /> <Products /> <Orders /> <Settings /> </Suspense> </main> </div> </div> ); } export default App; 

2. Single-SPA

// 正确姿势:Single-SPA // 1. 安装依赖 // npm install single-spa single-spa-react // 2. 注册应用 // src/registerApplications.js import { registerApplication, start } from 'single-spa'; registerApplication({ name: '@my-org/dashboard', app: () => import('@my-org/dashboard'), activeWhen: (location) => location.pathname.startsWith('/dashboard'), }); registerApplication({ name: '@my-org/users', app: () => import('@my-org/users'), activeWhen: (location) => location.pathname.startsWith('/users'), }); registerApplication({ name: '@my-org/products', app: () => import('@my-org/products'), activeWhen: (location) => location.pathname.startsWith('/products'), }); registerApplication({ name: '@my-org/orders', app: () => import('@my-org/orders'), activeWhen: (location) => location.pathname.startsWith('/orders'), }); registerApplication({ name: '@my-org/settings', app: () => import('@my-org/settings'), activeWhen: (location) => location.pathname.startsWith('/settings'), }); start(); // 3. 微应用配置 // packages/dashboard/src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import singleSpaReact from 'single-spa-react'; import Dashboard from './Dashboard'; const lifecycles = singleSpaReact({ React, ReactDOM, rootComponent: Dashboard, errorBoundary(err, info, props) { return <div>应用出错了</div>; }, }); export const bootstrap = lifecycles.bootstrap; export const mount = lifecycles.mount; export const unmount = lifecycles.unmount; 

3. Qiankun

// 正确姿势:Qiankun // 1. 安装依赖 // npm install qiankun // 2. 注册应用 // src/main.js import { registerMicroApps, start } from 'qiankun'; registerMicroApps([ { name: 'dashboard', entry: '//localhost:3001', container: '#micro-app-container', activeRule: '/dashboard', }, { name: 'users', entry: '//localhost:3002', container: '#micro-app-container', activeRule: '/users', }, { name: 'products', entry: '//localhost:3003', container: '#micro-app-container', activeRule: '/products', }, { name: 'orders', entry: '//localhost:3004', container: '#micro-app-container', activeRule: '/orders', }, { name: 'settings', entry: '//localhost:3005', container: '#micro-app-container', activeRule: '/settings', }, ]); start(); // 3. 主应用 // src/App.jsx import React from 'react'; import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom'; function App() { return ( <Router> <div> <nav> <Link to="/dashboard">仪表盘</Link> <Link to="/users">用户</Link> <Link to="/products">产品</Link> <Link to="/orders">订单</Link> <Link to="/settings">设置</Link> </nav> <div></div> </div> </Router> ); } export default App; // 4. 微应用配置 // packages/dashboard/src/main.js import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; let instance = null; function render(props) { const { container } = props; instance = createApp(App); instance.use(router); instance.mount(container ? container.querySelector('#app') : '#app'); } if (!window.__POWERED_BY_QIANKUN__) { render({}); } export async function bootstrap() { console.log('dashboard bootstraped'); } export async function mount(props) { console.log('dashboard mounted', props); render(props); } export async function unmount() { console.log('dashboard unmounted'); instance.unmount(); instance = null; } 

毒舌点评:这才叫前端微前端,将应用拆分成多个独立的微应用,团队协作更高效,构建时间更短,再也不用担心巨石应用的问题了。

Read more

忘掉 MCP?OpenClaw 作者说:CLI 才是 AI 连接世界的终极接口

大家好,我是Tony Bai。 如果回望 2025 年上半年,AI 圈最火的技术关键词无疑是 MCP (Model Context Protocol)。彼时,行业内满怀希望地为智能体定义 Schema,构建 JSON-RPC 服务,试图为 AI 打造一套标准化的能力连接协议。 然而,时间来到 2026 年初,技术圈的热点正在悄然发生偏移。 最近,一个名为 OpenClaw(其前身是火遍全网的 Moltbot/Clawdbot)的开源项目,用一种极其“复古”的方式给所有人上了一课。其作者 Peter Steinberger 提出了一个极其犀利的观点:与其费力去对齐协议,不如直接回归 CLI(命令行)。 在 OpenClaw 的世界里,要让智能体获得一项新能力——无论是控制智能家居、管理

5款国产免费AI代码助手全方位评测:谁才是真正的编程助手?大模型入门到精通,收藏这篇就足够了!

5款国产免费AI代码助手全方位评测:谁才是真正的编程助手?大模型入门到精通,收藏这篇就足够了!

人工智能在代码编写领域的应用展现了最直接的生产力提升。然而,诸如ChatGPT和Cloud等工具不仅收费,还存在访问限制。 为此,我们将评测五款国内热门的免费AI代码助手。这些工具不仅对个人用户免费开放,且在国内可无障碍使用。 通过一系列从简单到复杂的游戏编程任务,我们将评估这些AI编程工具在实际开发场景中提升编程效率的表现。 我们将评测的5款AI代码助手如下: 1. 抖音的豆包MarsCode 2. 百度文心的快码 3. 阿里云的通义零码 4. 腾讯云的AI代码助手 5. 玺哥超Carry 前四款均为顶级大厂产品,第五款是通过百度搜索发现的。所有评测的AI助手均可在VSCode中免费使用。 首先,展示一个由AI生成的俄罗斯方块游戏。请猜测这是由哪个AI助手生成的,并将答案发送至弹幕。 我们的目标是找出能够帮助普通用户解决日常编程问题的AI助手。为此,我们设计了五个由简至繁的游戏编程任务。 每个任务都将使用相同的详细提示词。所有AI助手将尝试完成全部任务,我们将根据其表现进行评分。评分标准涵盖五个方面,总分100分。 一、功能完整性(30分):程序是否实现了

零基础学AI大模型之RAG系统链路构建:文档切割转换全解析

零基础学AI大模型之RAG系统链路构建:文档切割转换全解析

大家好,我是工藤学编程 🦉一个正在努力学习的小博主,期待你的关注实战代码系列最新文章😉C++实现图书管理系统(Qt C++ GUI界面版)SpringBoot实战系列🐷【SpringBoot实战系列】SpringBoot3.X 整合 MinIO 存储原生方案分库分表分库分表之实战-sharding-JDBC分库分表执行流程原理剖析消息队列深入浅出 RabbitMQ-RabbitMQ消息确认机制(ACK)AI大模型零基础学AI大模型之LangChain WebBaseLoader与Docx2txtLoader实战 前情摘要 1、零基础学AI大模型之读懂AI大模型 2、零基础学AI大模型之从0到1调用大模型API 3、零基础学AI大模型之SpringAI 4、零基础学AI大模型之AI大模型常见概念 5、零基础学AI大模型之大模型私有化部署全指南 6、零基础学AI大模型之AI大模型可视化界面 7、零基础学AI大模型之LangChain 8、零基础学AI大模型之LangChain六大核心模块与大模型IO交互链路 9、零基础学AI大模型之Prompt提示词工程 10、零基础学

Cursor vs Claude Code vs Codex:三款 AI 编程工具深度对比

Cursor vs Claude Code vs Codex:三款 AI 编程工具深度对比

图:三款工具各有所长,选对工具事半功倍 前言 上一篇我们聊了「为什么每个开发者都要学会用 AI 写代码」,今天进入实战:市面上最热门的三款 AI 编程工具——Cursor、Claude Code、GitHub Copilot/Codex,到底有什么区别?该怎么选? 这三款工具代表了 AI 编程的三种不同路径: * Cursor → AI 原生 IDE,改造你的编辑器 * Claude Code → 终端 AI Agent,帮你跑腿干活 * GitHub Copilot / Codex → 嵌入式助手,融入现有工作流 让我们逐一拆解。 一、Cursor:AI 原生 IDE 的代表 图:Cursor 基于 VS