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

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

毒舌时刻

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

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

为什么你需要微前端

最近看到一个项目,代码量超过 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

微搭低代码MBA 培训管理系统实战 19——教务管理:从订单到课时卡的自动转化

微搭低代码MBA 培训管理系统实战 19——教务管理:从订单到课时卡的自动转化

目录 * 前情回顾 * 一、 数据源设计 * 1.1 学员档案表 (`MBA_StudentProfiles`) * 1.2 课时卡表 (`MBA_LearningCards`) * 二 创建管理页面 * 2.1 搭建财务布局 * 2.2 搭建待支付列表页面 * 2.3 搭建确认支付弹窗 * 2.4 自动化开课 * 三 配置门户数据 * 最终效果 * 总结 前情回顾 上一篇中我们讲解了销售在订单成交后,录入订单。此时订单的状态还是待支付的状态,需要财务确认收款情况。财务人员点击了"确认收款",订单状态变更为 已清账。此时,资金流已经闭环,但学员在系统里还只是一个"商机客户",没有上课的权限。

漫画脸描述生成实战手册:生成符合Stable Diffusion WebUI语法的Prompt结构

漫画脸描述生成实战手册:生成符合Stable Diffusion WebUI语法的Prompt结构 你是不是也遇到过这种情况?脑子里有一个超棒的二次元角色形象,但打开Stable Diffusion WebUI,面对空白的提示词输入框,却不知道从何写起。写“一个可爱的女孩”?生成的图片太普通。想描述得详细点,又怕语法不对,AI根本理解不了。 别担心,这正是“漫画脸描述生成”工具要帮你解决的痛点。它就像一个懂二次元、又精通AI绘画语法的“角色设计师”,你只需要用大白话描述想法,它就能帮你生成一套可以直接复制粘贴、让AI绘图工具“秒懂”的详细Prompt。 今天,我们就来手把手教你,如何用这个工具,从零开始,生成一份专业、精准、符合Stable Diffusion WebUI语法的漫画角色描述。 1. 从零开始:快速上手漫画脸描述生成 1.1 环境准备:一键启动你的专属角色设计师 使用“漫画脸描述生成”工具非常简单,它已经封装成了开箱即用的镜像。你不需要懂复杂的模型部署,

免费部署openClaw龙虾机器人(经典)

免费部署openClaw龙虾机器人(经典)

前几天出了个免费玩龙虾的详细教程,很多小伙伴觉得不错,但是还有一些新手留言反馈内容不够详细,这次我将重新梳理一遍,做一期更细致的攻略,同时扩展补充配置好之后的推荐(我认为是必要)操作,争取一篇文章让大家可以收藏起来,随时全套参照复用。 先看效果测试 部署完成基础运行效果测试,你可以直接问clawdbot当前的模型: 1.Token平台准备 首先,还是准备好我们可以免费撸的API平台 这里我找到了两个可以免费使用的API,测试之后执行效率还可以,下面将分别进行细致流程拆解。 1.1 硅基流动获取ApiKey (相对免费方案 推荐) 硅基流动地址:https://cloud.siliconflow.cn/i/6T57VxS2 如果有账号的直接登录,没有的注册一个账号,这个认证就送16元,可以直接玩收费模型,真香。认证完成后在API秘钥地方新建秘钥。 硅基流动里面很多模型原来是免费的,有了16元注册礼,很多收费的模型也相当于免费用了,我体验一下了原来配置免费模型还能用,也是值得推荐的。建议使用截图的第一个模型体验一下,我一直用它。 1.2 推理时代

.NET/JAVA集成GoView低代码可视化大屏完整案例详解【.NET篇】

.NET/JAVA集成GoView低代码可视化大屏完整案例详解【.NET篇】

文章目录 * 一、GoView简介 * 二、.NET集成GoView方案 * 三、集成步骤详解 * 1. 环境准备 * 2. 获取并构建GoView * 3. 创建.NET项目 * 5. 修改.NET路由配置 * 6. 配置API接口 * 7. 修改GoView配置 * 四、进阶集成方案 * 1. 身份验证集成 * 2. 动态主题切换 * 3. 数据缓存优化 * 五、常见问题解决 * 1.跨域问题: * 2. 静态文件404错误: * 3. API请求路径问题: * 4. 性能优化: * 六、总结 一、GoView简介 GoView 是一款基于 Vue3.x 构建的低代码数据可视化开发平台,它允许开发者通过简单的配置快速构建各种数据可视化大屏。 * 官网文档: