文章目录
- 一. 什么是微前端
- 二. 微前端的优势
- 三. 微前端的多种实现
- 3.1 iframe
- iframe子窗口调用父窗口的方法
- iframe父窗口调用子窗口方法
- iframe子窗口向父窗口通信
- iframe的父窗口传递参数给子窗口
- 3.2 服务端模板组合
- 3.3 微前端框架 single-spa
- 3.4 微前端框架 qiankun
- 3.5 微前端microApp
一. 什么是微前端
“微前端架构”就是构建基于微服务的前端应用架构。
其思想是将前端应用切分为一系列可以单独部署的松耦合的应用,然后将这些应用组装起来创建单个面向用户的应用程序。
二. 微前端的优势
- 降低代码耦合
- 独立开发、独立部署
- 增量升级:微前端是一种非常好的实施渐进式重构的手段和策略
- 独立运行时,每个微应用之间状态隔离,运行时状态不共享
- 团队可以按照业务垂直拆分更高效
三. 微前端的多种实现
3.1 iframe
iframe天然具备微前端的基因。我们只需将单体的前端应用,按照业务模块进行拆分,分别部署。最后通过iframe进行动态加载即可。
<html> <head> <title>微前端-ifame</title> </head> <body> <h1>我是容器</h1> <iframe id="mfeLoader"></iframe> <script type="text/javascript"> const routes = { '/': 'https://app.com/index.html', '/app1': 'https://app1.com/index.html', '/app2': 'https://app2.com/index.html', }; const iframe = document.querySelector('#mfeLoader'); iframe.src = routes[window.location.pathname]; </script> </body> </html>优点:
- 实现简单
- 天然具备隔离性
缺点:
- 主页面和 iframe 共享最大允许的 HTTP 链接数。
- iframe 阻塞主页面加载。
- 浏览器的后退按钮无效
iframe子窗口调用父窗口的方法
在iframe的页面中,通过JavaScript编写代码来调用父组件的方法。可以使用window.parent或window.top来引用父窗口对象,然后调用父窗口的方法。
例如,假设父组件中有一个名为"handleClick"的方法,可以在iframe的页面中使用以下代码来调用它:
window.parent.handleClick(); // 或者 window.top.handleClick();iframe父窗口调用子窗口方法
在父窗口中,通过JavaScript获取iframe的引用,然后使用contentWindow属性访问子窗口的对象
var iframe = document.getElementById('myIframe'); var childWindow = iframe.contentWindow; childWindow.handleClick();iframe子窗口向父窗口通信
postMessage用于在不同的域之间发送消息。它允许你发送消息到父窗口,并接收来自父窗口的消息。
在 iframe 中:
window.parent.postMessage('Hello from iframe!', 'http://example.com');在父窗口中:
window.addEventListener('message', function(event) { if (event.origin !== 'http://example.com') return; // 验证消息来源 console.log('Received message from iframe:', event.data); }, false);iframe的父窗口传递参数给子窗口
方法一:父窗口可以使用window.postMessage方法向子窗口发送消息
var iframe = document.getElementById('myIframe'); iframe.contentWindow.postMessage('Hello from parent!', '*');在子窗口中,可以使用以下代码监听消息:
window.addEventListener('message', function(event) { if (event.origin !== 'http://example.com') return; // 验证消息来源 console.log('Received message from parent:', event.data); }, false);方法二:使用URL查询参数:如果父窗口和子窗口处于同一域下,并且没有跨域限制,父窗口可以通过修改iframe的src属性,将参数作为URL查询参数传递给子窗口。在父窗口中,可以使用以下代码将参数作为URL查询参数传递给子窗口:
var iframe = document.getElementById('myIframe'); iframe.src = 'child.html?param1=value1¶m2=value2';在子窗口中,可以通过JavaScript获取URL查询参数:
var param1 = getUrlParam('param1'); // 获取URL查询参数的方法,可以根据实际情况实现 var param2 = getUrlParam('param2'); // 获取URL查询参数的方法,可以根据实际情况实现3.2 服务端模板组合
常见的实现方式是,服务端根据路由动态渲染特定页面的模板文件。架构图如下:
优点:
- 实现简单
- 技术栈独立
缺点:
- 需要额外配置 Nginx
- 前后端分离不彻底
3.3 微前端框架 single-spa
借助single-spa,开发者可以为不同的子应用使用不同的技术栈,比如子应用 A 使用vue开发,子应用 B 使用react开发,完全没有历史债务。
single-spa 的实现原理并不难,从架构上来讲可以分为两部分:子应用和容器应用。
子应用与传统的单页应用的区别在于:
- 不需要 HTML 入口文件,
- js 入口文件导出的模块,必须包括 bootstrap、mount 和 unmount 三个方法。
容器应用主要负责注册应用,当 url 命中子应用的路由时激活并挂载子应用,或者当子应用不处于激活状态时,将子应用从页面中移除卸载。其核心方法有两个:
registerApplication注册并下载子应用start启动处于激活状态的子应用。
容器应用代码
<html> <body> <script src="single-spa-config.js"></script> </body> </html>single-spa-config.js代码如下:
import * as singleSpa from 'single-spa'; const appName = 'app1'; const app1Url = 'http://app1.com/app1.js' // loadJS 方法是伪代码,表示加载 app1.js。开发者需要自己实现,或者借助 systemJS 来实现。 singleSpa.registerApplication('app1',() => loadJS(app1Url), location => location.pathname.startsWith('/app1')) singleSpa.start();子应用代码:
//app1.js let domEl; export function bootstrap(props) { return Promise .resolve() .then(() => { domEl = document.createElement('div'); domEl.id = 'app1'; document.body.appendChild(domEl); }); } export function mount(props) { return Promise .resolve() .then(() => { domEl.textContent = 'App 1 is mounted!' }); } export function unmount(props) { return Promise .resolve() .then(() => { domEl.textContent = ''; }) }优点:
- 纯前端解决方案
- 可以使用多种技术栈
- 完善的生态
缺点:
- 上手成本高
- 需要改造现有应用
- 跨应用的联调变得复杂
3.4 微前端框架 qiankun
qiankun是一个基于single-spa的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
在主应用中注册微应用
import { registerMicroApps, start } from 'qiankun'; registerMicroApps([ { name: 'react app', // app name registered entry: '//localhost:7100', container: '#yourContainer', activeRule: '/yourActiveRule', }, { name: 'vue app', entry: { scripts: ['//localhost:7100/main.js'] }, container: '#yourContainer2', activeRule: '/yourActiveRule2', }, ]); start();当微应用信息注册完之后,一旦浏览器的 url 发生变化,便会自动触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子。
微应用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js) 导出bootstrap、mount、unmount三个生命周期钩子,以供主应用在适当的时机调用。
/** * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。 */ export async function bootstrap() { console.log('react app bootstraped'); } /** * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 */ export async function mount(props) { ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root')); } /** * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例 */ export async function unmount(props) { ReactDOM.unmountComponentAtNode( props.container ? props.container.querySelector('#root') : document.getElementById('root'), ); } /** * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效 */ export async function update(props) { console.log('update props', props); }优点:
- 简单:qiankun 对于用户而言只是一个类似 jQuery 的库,你需要调用几个 qiankun 的 API 即可完成应用的微前端改造
- 解耦/技术栈无关
- 完善的生态
缺点:
- 上手成本高
- 需要改造现有应用
- 跨应用的联调变得复杂
3.5 微前端microApp
main.ts中初始化micro-app和相关配置
/** * micro-app 微前端 */ import microApp from '@micro-zoe/micro-app'; microApp.start({ 'disable-memory-router': true, // 关闭虚拟路由系统 'disable-patch-request': true, // 关闭对子应用请求的拦截 lifeCycles: { created() { // console.log('created'); }, beforemount() { // console.log('beforemount'); }, mounted() { console.log('fst', performance.now().toFixed()); // 首屏时间 // console.log('mounted'); }, unmount() { console.log('unmount'); }, error(e) { Sentry.captureException(new Error('主站Error:生命周期错误'), { level: 'error', extra: { ...e } }); } } }); microApp.router.setBaseAppRouter(router); microApp.router.beforeEach({ 'micoro-app-homeweb-app': (to, from) => { const toQuery = qs.parse(to.search, { ignoreQueryPrefix: true }); const fromQuery = qs.parse(from.search, { ignoreQueryPrefix: true }); if ( toQuery.type !== fromQuery.type || (from.pathname === '/search' && fromQuery.threadId && !toQuery.threadId && toQuery.type === 'chat') ) { // 设置全局ref savePageRef(to.fullPath); } else if (to.pathname === '/search' && toQuery.type === 'chat' && toQuery.threadId) { const BASE_URL = (import.meta as any).env.VITE_HOST; sessionStorage.setItem('ref', BASE_URL + to.fullPath); } else { savePageRef(to.fullPath); } } }); microApp.router.afterEach({ 'micoro-app-homeweb-app': (to, from) => { const names = { '/': '首页', '/search': '搜索', '/g-star': 'g-star', '/g-star/apply': 'g-star 申请', '/explore': '搜索开源' }; const toQuery = qs.parse(to.search, { ignoreQueryPrefix: true }); if (to.pathname === '/search' && toQuery.type !== 'repo') { // 对话有threadid后上报 if (toQuery.threadId) useReport('pageview', {}, { 'homeweb-page-title': names[to.pathname] }); } else { useReport('pageview', {}, { 'homeweb-page-title': names[to.pathname] }); } } });- 路由中添加micorApp名称
{ path: '/', component: DefaultLayout, children: [ { path: '', name: 'home', component: () => import('@/views/micro-page/proxy-homeweb.vue'), meta: { micorApp: ['micoro-app-homeweb-app'], hasMobile: true, hiddenFooter: true, reportTitle: '首页', className: 'w-full min-w-full', headerClassName: '' } }, ... ] }- Layout.vue中添加相关路由守卫和监听器
microApp.router.afterEach({ 'micoro-app-homeweb-app': (to, from) => { outOfSearch.value = to.pathname !== '/search'; } }); const checkPage = (data: any) => { if (data.type === 'checkPage') { return 'ready'; } }; onMounted(() => { microApp.addDataListener('micoro-app-homeweb-app', checkPage, false); }); onUnmounted(() => { microApp.removeDataListener('micoro-app-homeweb-app', checkPage); });- 页面中加载微应用
<template> <div id="homeweb-container"></div> </template> onMounted(() => { toolbarContain.value = document.getElementById('toolbarBottom'); microApp.renderApp({ name: 'micoro-app-homeweb-app', url: origin, container: '#homeweb-container', data: { emitter, toolbarContain, $router: router }, iframe: true, baseroute: '/', defaultPtah: route.path }); }); onBeforeUnmount(() => { microApp.unmountApp('micoro-app-homeweb-app'); });这是前端程序员在某红薯平台自述前端被裁的真实经历!
2025开年,AI技术打得火热,正在改变前端人的职业命运:
阿里云核心业务全部接入Agent体系;
字节跳动30%前端岗位要求大模型开发能力;
腾讯、京东、百度开放招聘技术岗,80%与AI相关……
大模型正在重构技术开发范式,传统CRUD开发模式正在被AI原生应用取代!
最残忍的是,业务面临转型,领导要求用RAG优化知识库检索,你不会;带AI团队,微调大模型要准备多少数据,你不懂;想转型大模型应用开发工程师等相关岗,没项目实操经验……这不是技术焦虑,而是职业生存危机!
曾经React、Vue等热门的开发框架,已不再是就业的金钥匙。如果认为会调用API就是懂大模型、能进行二次开发,那就大错特错了。制造、医疗、金融等各行业都在加速AI应用落地,未来企业更看重能用AI大模型技术重构业务流的技术人。
如今技术圈降薪裁员频频爆发,传统岗位大批缩水,相反AI相关技术岗疯狂扩招,薪资逆势上涨150%,大厂老板们甚至开出70-100W年薪,挖掘AI大模型人才!
不出1年 “有AI项目开发经验”或将成为前端人投递简历的门槛。
风口之下,与其像“温水煮青蛙”一样坐等被行业淘汰,不如先人一步,掌握AI大模型原理+应用技术+项目实操经验,“顺风”翻盘!
大模型目前在人工智能领域可以说正处于一种“炙手可热”的状态,吸引了很多人的关注和兴趣,也有很多新人小白想要学习入门大模型,那么,如何入门大模型呢?
下面给大家分享一份2025最新版的大模型学习路线,帮助新人小白更系统、更快速的学习大模型!
2025最新版CSDN大礼包:《AGI大模型学习资源包》免费分享**
一、2025最新大模型学习路线
一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。大模型领域涉及的知识点非常广泛,没有明确的学习路线可能会导致新人感到迷茫,不知道应该专注于哪些内容。
我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。
L1级别:AI大模型时代的华丽登场
L1阶段:我们会去了解大模型的基础知识,以及大模型在各个行业的应用和分析;学习理解大模型的核心原理,关键技术,以及大模型应用场景;通过理论原理结合多个项目实战,从提示工程基础到提示工程进阶,掌握Prompt提示工程。
L2级别:AI大模型RAG应用开发工程
L2阶段是我们的AI大模型RAG应用开发工程,我们会去学习RAG检索增强生成:包括Naive RAG、Advanced-RAG以及RAG性能评估,还有GraphRAG在内的多个RAG热门项目的分析。
L3级别:大模型Agent应用架构进阶实践
L3阶段:大模型Agent应用架构进阶实现,我们会去学习LangChain、 LIamaIndex框架,也会学习到AutoGPT、 MetaGPT等多Agent系统,打造我们自己的Agent智能体;同时还可以学习到包括Coze、Dify在内的可视化工具的使用。
L4级别:大模型微调与私有化部署
L4阶段:大模型的微调和私有化部署,我们会更加深入的探讨Transformer架构,学习大模型的微调技术,利用DeepSpeed、Lamam Factory等工具快速进行模型微调;并通过Ollama、vLLM等推理部署框架,实现模型的快速部署。
整个大模型学习路线L1主要是对大模型的理论基础、生态以及提示词他的一个学习掌握;而L3 L4更多的是通过项目实战来掌握大模型的应用开发,针对以上大模型的学习路线我们也整理了对应的学习视频教程,和配套的学习资料。
二、大模型经典PDF书籍
书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。(书籍含电子版PDF)
三、大模型视频教程
对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识。
四、大模型项目实战
学以致用,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。
五、大模型面试题
面试不仅是技术的较量,更需要充分的准备。
在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
2025最新版CSDN大礼包:《AGI大模型学习资源包》免费分享