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

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

毒舌时刻

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

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

为什么你需要微前端

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

WebP格式简记

文章目录 * 概述 * 开发背景 * 核心技术原理 * 有损压缩 * 无损压缩 * 动画与扩展功能 * 核心技术特性 * 兼容性现状与性能 * 全平台生态支持 * 编解码性能表现 * 实际应用与生态 * 核心应用要点 * 工具与生态支持 * 优缺点与发展趋势 * 核心优缺点 * 发展趋势 概述 WebP(Web Picture)是由Google开发的开源光栅图像格式,自2010年推出以来,凭借高压缩效率与全功能支持的技术特性,逐步成为替代JPEG、PNG、GIF的现代Web图像标准,更是网页性能优化、移动端资源轻量化的核心选择。 该格式基于视频编码技术创新,完美解决了传统图像格式在压缩率、功能兼容性上的痛点,目前已被纳入W3C标准,成为跨端图像传输的主流方案,其核心目标是提升网页加载速度、降低带宽消耗,特别适用于Web和移动应用场景。 对于绝大多数Web应用而言,将JPEG/PNG/GIF迁移至WebP可带来显著的性能收益,且实施成本低、风险可控,WebP已从“可选优化”转变为现代Web开发的标准实践。

高铁轨道探伤:GLM-4.6V-Flash-WEB识别钢轨磨损痕迹

高铁轨道探伤:GLM-4.6V-Flash-WEB识别钢轨磨损痕迹 在高铁日均运行里程突破数万公里的今天,一条看不见的“神经网络”正在悄然守护着每一寸轨道的安全——那就是基于人工智能的自动化检测系统。传统靠人工敲击、目视巡检的时代正被快速淘汰,取而代之的是能在毫秒内完成图像分析、语义理解甚至风险预判的智能视觉引擎。这其中,一个名为 GLM-4.6V-Flash-WEB 的多模态模型,正以其“轻量但聪明”的特质,在钢轨表面缺陷识别任务中崭露头角。 想象这样一个场景:一列轨道检测车以80km/h的速度前行,底部摄像头每秒拍摄数十帧高清图像。这些画面不再是等待人工翻阅的静态文件,而是实时流入边缘计算设备中的数据流。就在列车驶过的一瞬间,AI已判断出某段左轨中部存在一条长约12厘米的线状磨损失效,并标记为二级风险,同步上传至运维平台。整个过程延迟不足300毫秒。这背后,正是 GLM-4.6V-Flash-WEB 所代表的新一代视觉语言模型带来的变革。 多模态认知如何重塑工业检测逻辑? 过去十年,计算机视觉在工业质检领域主要依赖YOLO、Mask R-CNN等目标检测框架。它们擅长“找

cv_unet_image-colorization环境部署:CPU/GPU自动适配配置指南

cv_unet_image-colorization环境部署:CPU/GPU自动适配配置指南 1. 引言 黑白老照片承载着珍贵的记忆,但缺少色彩总让人觉得少了些温度。过去,给老照片上色是件费时费力的专业活,需要设计师对色彩有深刻的理解。现在,借助AI技术,我们普通人也能轻松为黑白照片注入色彩。 今天要介绍的工具,就是一个基于深度学习模型的本地化图像上色工具。它最大的特点是完全在本地运行,你的照片数据不会上传到任何云端服务器,隐私安全有保障。无论你是想修复家族老照片,还是处理黑白摄影作品,这个工具都能帮上忙。 更棒的是,这个工具能自动识别你的电脑配置。如果你有独立显卡(GPU),它会自动调用GPU加速,处理速度飞快;如果没有显卡,它也能在CPU上稳定运行。接下来,我就手把手教你如何部署和使用这个工具。 2. 工具核心原理:UNet架构 在开始部署之前,我们先简单了解一下这个工具背后的技术原理。理解了原理,使用起来会更得心应手。 2.1 UNet是什么? UNet是一种专门为图像处理设计的神经网络架构。你可以把它想象成一个非常聪明的“色彩专家”,它经过大量训练后,学会了

前端实现实现视频播放的方案和面试问题

作为 Web 前端工程师,视频播放是高频且核心的业务场景之一,涉及原生 API、播放器封装、兼容性、性能优化、高级功能 等多个维度。以下从「基础技术层」「核心实现方案」「进阶功能」「性能与兼容」四个层面,系统拆解视频播放的技术体系和落地方式。 一、核心基础技术:Web 视频播放的底层支撑 首先要明确 Web 端视频播放的核心技术底座,所有播放器都是基于这些基础能力封装而来。 1. HTML5 原生<video>标签(最基础) HTML5 推出的<video>标签是 Web 视频播放的基石,无需插件(如 Flash),原生支持视频渲染,是所有前端视频播放的起点。 * 最简实现示例: 核心属性(必掌握)