《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux... 。

文章目录
- 一、本文面试题目录
-
-
- [44. 微前端项目的目录结构通常如何设计?](#44. 微前端项目的目录结构通常如何设计?)
- [45. 微前端中如何实现子应用的独立开发、独立测试和独立部署?](#45. 微前端中如何实现子应用的独立开发、独立测试和独立部署?)
-
- [1. 独立开发](#1. 独立开发)
- [2. 独立测试](#2. 独立测试)
- [3. 独立部署](#3. 独立部署)
- [46. 微前端项目的构建流程与传统SPA有什么区别?](#46. 微前端项目的构建流程与传统SPA有什么区别?)
- [47. 如何解决微前端中子应用构建后的资源路径问题?(如publicPath配置)](#47. 如何解决微前端中子应用构建后的资源路径问题?(如publicPath配置))
-
- [1. 动态设置`publicPath`](#1. 动态设置
publicPath
) - [2. 构建时固定`publicPath`](#2. 构建时固定
publicPath
) - [3. 图片等静态资源处理](#3. 图片等静态资源处理)
- [1. 动态设置`publicPath`](#1. 动态设置
- [48. 微前端中如何处理子应用的版本管理?](#48. 微前端中如何处理子应用的版本管理?)
-
- [1. 版本号嵌入资源路径](#1. 版本号嵌入资源路径)
- [2. 版本管理服务](#2. 版本管理服务)
- [3. 基于Git的版本控制](#3. 基于Git的版本控制)
- [49. 微前端项目的CI/CD流程如何设计?](#49. 微前端项目的CI/CD流程如何设计?)
-
- [1. 子应用CI/CD流程](#1. 子应用CI/CD流程)
- [2. 基座应用CI/CD流程](#2. 基座应用CI/CD流程)
- [50. 子应用部署后,基座应用如何感知并加载最新版本的子应用?](#50. 子应用部署后,基座应用如何感知并加载最新版本的子应用?)
-
- [1. 配置中心拉取](#1. 配置中心拉取)
- [2. 版本号自动拼接](#2. 版本号自动拼接)
- [3. 本地存储缓存 + 定时刷新](#3. 本地存储缓存 + 定时刷新)
- [51. 微前端中如何实现灰度发布和A/B测试?](#51. 微前端中如何实现灰度发布和A/B测试?)
-
- [1. 基于配置中心的灰度规则](#1. 基于配置中心的灰度规则)
- [2. A/B测试工具集成](#2. A/B测试工具集成)
- [52. 微前端项目中,如何统一管理各应用的依赖版本?](#52. 微前端项目中,如何统一管理各应用的依赖版本?)
-
- [1. 共享依赖(externals + 基座提供)](#1. 共享依赖(externals + 基座提供))
- [2. 依赖版本锁(如pnpm workspace)](#2. 依赖版本锁(如pnpm workspace))
- [3. 依赖检查工具](#3. 依赖检查工具)
- [53. 微前端对浏览器的兼容性如何?需要注意哪些问题?](#53. 微前端对浏览器的兼容性如何?需要注意哪些问题?)
-
- [1. 主流框架兼容性](#1. 主流框架兼容性)
- [2. 关键兼容性问题](#2. 关键兼容性问题)
- [3. 兼容处理建议](#3. 兼容处理建议)
- [54. 不同技术栈的子应用(如Vue2、Vue3、React18)共存时可能遇到哪些问题?如何解决?](#54. 不同技术栈的子应用(如Vue2、Vue3、React18)共存时可能遇到哪些问题?如何解决?)
-
- [1. 常见问题](#1. 常见问题)
- [2. 解决方案](#2. 解决方案)
- [55. 微前端中如何处理子应用的路由历史模式(hash/history)冲突?](#55. 微前端中如何处理子应用的路由历史模式(hash/history)冲突?)
-
- [1. 统一路由前缀](#1. 统一路由前缀)
- [2. 基座路由分发配置(以Vue Router为例)](#2. 基座路由分发配置(以Vue Router为例))
- [3. 子应用路由适配](#3. 子应用路由适配)
- [4. 路由同步](#4. 路由同步)
- [56. 子应用卸载时,如何确保资源(事件、定时器、DOM)被彻底清理?](#56. 子应用卸载时,如何确保资源(事件、定时器、DOM)被彻底清理?)
-
- [1. 清理事件监听](#1. 清理事件监听)
- [2. 清除定时器/间隔器](#2. 清除定时器/间隔器)
- [3. 销毁DOM与框架实例](#3. 销毁DOM与框架实例)
- [4. 清理全局变量与缓存](#4. 清理全局变量与缓存)
- [57. 微前端中遇到内存泄漏问题该如何排查和解决?](#57. 微前端中遇到内存泄漏问题该如何排查和解决?)
-
- [1. 排查工具与方法](#1. 排查工具与方法)
- [2. 常见泄漏场景与解决](#2. 常见泄漏场景与解决)
- [3. 预防措施](#3. 预防措施)
- [58. 子应用加载失败时,如何进行错误捕获和降级处理?](#58. 子应用加载失败时,如何进行错误捕获和降级处理?)
-
- [1. 错误捕获机制](#1. 错误捕获机制)
- [2. 降级处理方案](#2. 降级处理方案)
- [59. 微前端中如何处理跨域问题?](#59. 微前端中如何处理跨域问题?)
-
- [1. 资源加载跨域(JS、CSS、图片)](#1. 资源加载跨域(JS、CSS、图片))
- [2. 接口请求跨域](#2. 接口请求跨域)
- [3. iframe跨域通信(若使用iframe集成)](#3. iframe跨域通信(若使用iframe集成))
- [60. 微前端项目中,如何调试子应用?](#60. 微前端项目中,如何调试子应用?)
-
- [1. 独立调试](#1. 独立调试)
- [2. 集成到基座调试](#2. 集成到基座调试)
- [3. 框架特定调试工具](#3. 框架特定调试工具)
- [4. 日志与调试工具](#4. 日志与调试工具)
- [5. 远程调试](#5. 远程调试)
-
- 二、88道微前端面试题目录列表
一、本文面试题目录
44. 微前端项目的目录结构通常如何设计?
微前端项目的目录结构设计需兼顾基座应用与子应用的独立性,同时保证协作效率。通常采用"基座 + 子应用"的多仓库或单仓库(monorepo)结构,以下是常见设计方案:
-
多仓库结构(推荐,适合大型团队)
micro-frontend-project/ ├── base-app/ # 基座应用(独立仓库) │ ├── public/ │ ├── src/ │ │ ├── router/ # 基座路由(负责分发子应用) │ │ ├── apps/ # 子应用注册配置 │ │ ├── communication/ # 应用通信机制(如Pub/Sub) │ │ └── ... │ └── package.json ├── app-vue/ # Vue子应用(独立仓库) │ ├── public/ │ ├── src/ │ └── package.json ├── app-react/ # React子应用(独立仓库) │ ├── public/ │ ├── src/ │ └── package.json └── docs/ # 文档(共享规范、API等)
-
Monorepo结构(适合中小型团队)
使用lerna或pnpm workspace管理,所有应用放在同一仓库:
micro-frontend-project/ ├── packages/ │ ├── base-app/ # 基座应用 │ ├── app-vue/ # Vue子应用 │ ├── app-react/ # React子应用 │ └── shared/ # 共享工具库(如通信函数、类型定义) ├── lerna.json # 或pnpm-workspace.yaml └── package.json
设计原则:
- 基座应用专注于路由分发、应用注册、通信管理,不包含业务逻辑。
- 子应用保持独立目录,可单独运行、构建和部署。
- 共享代码(如工具函数、类型定义)抽离为独立包,避免重复开发。
45. 微前端中如何实现子应用的独立开发、独立测试和独立部署?
微前端的核心目标之一是子应用自治,实现方式如下:
1. 独立开发
-
子应用提供独立运行入口 (如
public/index.html
),无需依赖基座即可启动。 -
开发环境中,子应用可通过Mock数据 模拟基座传递的参数(如
props
、全局状态)。 -
示例(Vue子应用独立开发配置):
javascript// 子应用main.js if (!window.__POWERED_BY_QIANKUN__) { // 独立运行时挂载 new Vue({ router, render: h => h(App) }).$mount('#app-vue'); } else { // 被基座加载时的生命周期(供Qiankun调用) export async function mount(props) { renderApp(props.container); } }
2. 独立测试
-
子应用编写单元测试 (Jest、Vitest)和E2E测试(Cypress、Playwright),测试环境与基座隔离。
-
测试时可通过环境变量模拟基座集成场景,例如:
bash# 独立测试命令 npm run test:unit # 模拟集成环境测试 VITE_IS_MICRO_APP=true npm run test:e2e
3. 独立部署
- 子应用打包后部署到独立域名或CDN,生成可访问的资源地址 (如
https://subapp-vue.example.com
)。 - 基座通过配置子应用的入口地址动态加载,无需重新部署基座即可更新子应用。
46. 微前端项目的构建流程与传统SPA有什么区别?
微前端构建流程需兼顾子应用独立构建 和基座集成兼容性,与传统SPA的区别如下:
维度 | 传统SPA | 微前端 |
---|---|---|
构建目标 | 单一应用打包为完整资源 | 子应用独立打包,输出可集成资源 |
资源依赖 | 内部依赖集中管理 | 需考虑依赖共享(如React、Vue) |
公共资源处理 | 直接打包到应用中 | 提取为共享库,避免重复打包 |
构建配置复杂度 | 单一配置文件 | 基座与子应用需单独配置,且需兼容 |
输出产物用途 | 直接部署运行 | 需被基座动态加载,需处理资源路径 |
示例(Qiankun子应用构建配置) :
子应用需禁用HTML压缩(避免基座解析失败),并配置libraryTarget
:
javascript
// Vue子应用vue.config.js
module.exports = {
configureWebpack: {
output: {
library: 'app-vue', // 子应用名称
libraryTarget: 'umd', // 输出为umd格式,支持动态加载
},
},
chainWebpack: config => {
config.plugins.delete('html'); // 禁用默认html插件(由基座管理HTML)
config.plugins.delete('preload'); // 禁用预加载,避免资源冲突
},
};
47. 如何解决微前端中子应用构建后的资源路径问题?(如publicPath配置)
子应用构建后若资源路径(如JS、CSS、图片)不正确,会导致加载失败。解决方式如下:
1. 动态设置publicPath
根据子应用的加载环境(独立运行或被基座加载)动态调整资源路径:
javascript
// 子应用入口文件(如main.js)
if (window.__POWERED_BY_QIANKUN__) {
// 被基座加载时,资源路径为子应用部署地址
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
} else {
// 独立运行时,资源路径为当前域名
__webpack_public_path__ = '/';
}
- 原理:
__webpack_public_path__
是Webpack提供的全局变量,用于动态设置资源基础路径。 - Qiankun会自动注入
__INJECTED_PUBLIC_PATH_BY_QIANKUN__
,指向子应用的部署地址。
2. 构建时固定publicPath
若子应用部署地址固定,可在构建配置中直接指定:
javascript
// Vue子应用vue.config.js
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? 'https://cdn.example.com/app-vue/' // 生产环境CDN地址
: '/' // 开发环境
};
3. 图片等静态资源处理
- 优先使用相对路径 (如
./assets/img/logo.png
),避免绝对路径导致的跨域或路径错误。 - 若使用CDN,确保图片URL在子应用和基座环境中均可访问。
48. 微前端中如何处理子应用的版本管理?
子应用版本管理需确保基座能精准加载指定版本,同时支持平滑更新,常见方案:
1. 版本号嵌入资源路径
部署时将版本号作为路径前缀,例如:
https://cdn.example.com/app-vue/v1.2.0/main.js
https://cdn.example.com/app-vue/v1.3.0/main.js
- 基座通过配置指定子应用版本(如
{ name: 'app-vue', entry: 'https://cdn.example.com/app-vue/v1.3.0/' }
)。 - 优点:版本隔离,可回滚至历史版本。
2. 版本管理服务
搭建独立的版本管理服务(如基于Redis或数据库),存储子应用的版本信息:
json
// 版本管理服务返回的数据
{
"app-vue": {
"latest": "v1.3.0",
"stable": "v1.2.0",
"beta": "v1.4.0-beta"
}
}
- 基座启动时从服务拉取版本配置,动态加载对应版本的子应用。
- 适合需要灰度发布、A/B测试的场景。
3. 基于Git的版本控制
通过Git标签(tag)管理版本,部署时根据tag打包:
bash
# 打标签
git tag v1.2.0
# 部署指定标签
git checkout v1.2.0 && npm run build && npm run deploy
49. 微前端项目的CI/CD流程如何设计?
微前端CI/CD需支持子应用独立部署 和基座联动部署,典型流程如下:
1. 子应用CI/CD流程
2. 基座应用CI/CD流程
关键设计点:
-
子应用部署不依赖基座,部署后自动更新版本信息。
-
基座部署前需验证与所有子应用的兼容性(如通过集成测试)。
-
示例(GitLab CI配置,子应用
.gitlab-ci.yml
):yamlstages: - lint - test - build - deploy lint: script: npm run lint test: script: npm run test:unit build: script: npm run build artifacts: paths: - dist/ deploy: script: - npm run deploy:cdn # 部署到CDN,路径含版本号 - curl -X POST https://version-service.example.com/update \ -d '{"app": "app-vue", "version": "v1.2.0"}'
50. 子应用部署后,基座应用如何感知并加载最新版本的子应用?
基座感知子应用更新的核心是动态获取最新配置,常见实现方式:
1. 配置中心拉取
-
基座启动时从配置中心(如Nacos、Apollo)拉取子应用的最新入口地址。
-
示例(Qiankun注册子应用):
javascript// 基座应用 async function registerApps() { // 从配置中心获取子应用配置 const appsConfig = await fetch('https://config.example.com/micro-apps'); // 注册子应用 appsConfig.forEach(app => { registerMicroApps([{ name: app.name, entry: app.entry, // 动态入口(含最新版本) container: '#app-container', activeRule: app.activeRule, }]); }); }
2. 版本号自动拼接
-
子应用部署路径固定为
https://cdn.example.com/{appName}/{version}/
,基座通过接口获取最新版本号拼接路径。 -
示例:
javascript// 获取最新版本 const latestVersion = await fetch('https://version-service.example.com/app-vue/latest'); const entry = `https://cdn.example.com/app-vue/${latestVersion}/`;
3. 本地存储缓存 + 定时刷新
- 基座首次加载时缓存子应用配置,定时(如5分钟)刷新配置,避免频繁请求配置中心。
51. 微前端中如何实现灰度发布和A/B测试?
灰度发布和A/B测试需根据用户特征(如用户ID、地区)分发不同版本的子应用,实现方式:
1. 基于配置中心的灰度规则
-
配置中心存储灰度规则(如"10%用户使用v2.0,其余用v1.0"),基座根据规则加载对应版本。
-
示例(灰度规则):
json{ "app-vue": { "rules": [ { "condition": "userId % 10 === 0", "version": "v2.0" }, { "condition": "default", "version": "v1.0" } ] } }
-
基座解析规则并匹配用户:
javascriptfunction getAppVersion(appName, userId) { const rules = configCenter.getRules(appName); for (const rule of rules) { if (rule.condition === 'default') return rule.version; if (eval(rule.condition)) return rule.version; // 实际中避免使用eval,可通过规则引擎实现 } }
2. A/B测试工具集成
-
使用专业工具(如Optimizely、阿里云A/B测试),通过基座注入的用户标识(如cookie)分发版本。
-
子应用根据基座传递的
abTestGroup
参数渲染不同内容:javascript// 子应用mount生命周期 export function mount(props) { const { abTestGroup } = props; // 基座传递的A/B测试分组 if (abTestGroup === 'groupA') { renderFeatureA(); } else { renderFeatureB(); } }
52. 微前端项目中,如何统一管理各应用的依赖版本?
依赖版本不一致可能导致冲突(如React双实例),统一管理方案:
1. 共享依赖(externals + 基座提供)
-
子应用通过
externals
排除公共依赖(如React、Vue),由基座全局引入。 -
示例(Vue子应用
vue.config.js
):javascriptmodule.exports = { configureWebpack: { externals: { vue: 'Vue', // 子应用不打包Vue,使用基座的Vue 'vue-router': 'VueRouter' } } };
-
基座需在
index.html
中提前引入共享依赖:html<script src="https://cdn.example.com/vue@3.3.4/vue.global.js"></script> <script src="https://cdn.example.com/vue-router@4.2.5/vue-router.global.js"></script>
2. 依赖版本锁(如pnpm workspace)
-
在Monorepo结构中,通过
pnpm-workspace.yaml
和package.json
的peerDependencies
统一版本:yaml# pnpm-workspace.yaml packages: - 'packages/*'
json// 子应用package.json { "peerDependencies": { "react": "^18.0.0" } }
3. 依赖检查工具
- 使用
depcheck
或自定义脚本检查子应用依赖版本,与基座版本不一致时报警。
53. 微前端对浏览器的兼容性如何?需要注意哪些问题?
微前端的兼容性主要取决于框架实现 和子应用技术栈,常见注意事项:
1. 主流框架兼容性
框架 | 最低兼容浏览器 | 限制 |
---|---|---|
Single-spa | IE11+ | 需引入polyfill支持ES6+特性 |
Qiankun | IE11+(沙箱功能IE不支持) | 快照沙箱、代理沙箱依赖ES6 Proxy |
Micro-app | IE11+ | Web Component在IE中需polyfill |
2. 关键兼容性问题
- ES6+特性 :子应用若使用箭头函数、
Promise
等,需通过Babel转译,并在低版本浏览器引入core-js
。 - CSS变量:若子应用使用CSS变量,IE11及以下不支持,需降级为固定值。
- 沙箱机制 :Qiankun的代理沙箱依赖
Proxy
,IE11不支持,需切换为快照沙箱(功能有限)。 - 路由模式 :子应用使用
history
模式时,IE11不支持pushState
,需兼容为hash
模式。
3. 兼容处理建议
-
在基座中统一引入公共polyfill(如
@babel/polyfill
)。 -
使用
browserslist
配置统一兼容目标:json// package.json { "browserslist": ["last 2 versions", "ie >= 11"] }
54. 不同技术栈的子应用(如Vue2、Vue3、React18)共存时可能遇到哪些问题?如何解决?
多技术栈共存是微前端的优势,但可能存在以下问题:
1. 常见问题
- 依赖冲突 :如Vue2和Vue3的
Vue
全局变量冲突,React17与React18的react-dom
不兼容。 - 样式隔离失效 :不同框架的样式前缀(如
v-
、rs-
)可能冲突。 - 事件冒泡冲突:子应用的事件(如点击、滚动)可能影响基座或其他子应用。
2. 解决方案
-
依赖隔离 :通过Qiankun的
externals
配置,让不同子应用使用独立的依赖副本(避免共享):javascript// 基座注册子应用时配置 registerMicroApps([ { name: 'app-vue2', entry: '//app-vue2.example.com', container: '#container', activeRule: '/vue2', props: { // 告知子应用不共享Vue shareVue: false } }, { name: 'app-vue3', entry: '//app-vue3.example.com', container: '#container', activeRule: '/vue3', } ]);
-
样式隔离 :使用CSS Modules或BEM命名规范,结合Qiankun的
strictStyleIsolation: true
开启Shadow DOM隔离。 -
事件隔离 :子应用事件绑定到自身容器,卸载时主动解绑:
javascript// 子应用unmount生命周期 export function unmount() { document.getElementById('app-vue2').removeEventListener('click', handleClick); }
55. 微前端中如何处理子应用的路由历史模式(hash/history)冲突?
子应用路由模式冲突会导致路由跳转异常,解决方式如下:
1. 统一路由前缀
为每个子应用分配独立的路由前缀,避免路径重叠:
- 基座路由:
/
(负责分发) - 子应用1(Vue):
/vue/*
(使用history模式) - 子应用2(React):
/react/*
(使用hash模式)
2. 基座路由分发配置(以Vue Router为例)
javascript
// 基座路由配置
const routes = [
{
path: '/vue',
name: 'vueApp',
component: () => import('./views/MicroApp.vue'), // 加载子应用的容器组件
children: [
{ path: ':pathMatch(.*)*', component: () => import('./views/MicroApp.vue') }
]
},
{
path: '/react',
name: 'reactApp',
component: () => import('./views/MicroApp.vue'),
children: [
{ path: ':pathMatch(.*)*', component: () => import('./views/MicroApp.vue') }
]
}
];
3. 子应用路由适配
-
history模式 :子应用路由基础路径设为前缀,如Vue子应用:
javascriptconst router = new VueRouter({ mode: 'history', base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/', // 基座中为/vue,独立运行时为/ routes: [...] });
-
hash模式 :子应用hash前添加前缀(如
#/react/page1
),避免与其他子应用的#/page1
冲突。
4. 路由同步
使用Qiankun的setDefaultMountApp
和onRouteChange
钩子同步基座与子应用路由:
javascript
// 基座监听路由变化,同步子应用
onRouteChange(({ currentPath }) => {
console.log('当前路由变化:', currentPath);
});
56. 子应用卸载时,如何确保资源(事件、定时器、DOM)被彻底清理?
子应用卸载不彻底会导致内存泄漏,需在unmount
生命周期中主动清理:
1. 清理事件监听
-
移除全局事件(如
window.scroll
、document.click
):javascript// 子应用mount时记录事件 let scrollHandler; export function mount() { scrollHandler = () => console.log('滚动'); window.addEventListener('scroll', scrollHandler); } // unmount时移除 export function unmount() { window.removeEventListener('scroll', scrollHandler); }
2. 清除定时器/间隔器
javascript
let timer;
export function mount() {
timer = setInterval(() => console.log('定时任务'), 1000);
}
export function unmount() {
clearInterval(timer);
}
3. 销毁DOM与框架实例
-
Vue子应用:
javascriptlet app; export function mount(props) { app = new Vue({ render: h => h(App) }).$mount(props.container); } export function unmount() { app.$destroy(); // 销毁Vue实例 app.$el.innerHTML = ''; // 清空DOM }
-
React子应用:
javascriptimport { unmountComponentAtNode } from 'react-dom'; let container; export function mount(props) { container = props.container; ReactDOM.render(<App />, container); } export function unmount() { unmountComponentAtNode(container); // 卸载React组件 container.innerHTML = ''; }
4. 清理全局变量与缓存
javascript
export function unmount() {
// 清理全局变量
delete window.appVueState;
// 清理缓存(如axios请求取消)
axiosCancelAll();
}
57. 微前端中遇到内存泄漏问题该如何排查和解决?
微前端的内存泄漏通常源于子应用卸载不彻底,排查与解决步骤:
1. 排查工具与方法
- 浏览器DevTools :
- 切换到"Memory"标签,点击"Take heap snapshot"记录初始内存。
- 加载并卸载子应用,再次记录内存快照。
- 对比两次快照,筛选"Detached DOM tree"(游离DOM)和子应用相关的对象(如Vue/React实例)。
- Performance面板:录制加载-卸载过程,查看内存曲线是否持续上升。
- 代码审查 :检查子应用
unmount
函数是否遗漏清理(如事件、定时器)。
2. 常见泄漏场景与解决
- 游离DOM :子应用卸载时未清空容器,导致DOM节点残留。
解决:unmount
时执行container.innerHTML = ''
。 - 未清理的事件监听 :全局事件(如
window.resize
)未移除。
解决:使用命名函数绑定事件,卸载时精准移除。 - 框架实例残留 :Vue/React实例未销毁,导致组件内存占用。
解决:调用框架提供的销毁方法(如$destroy
、unmountComponentAtNode
)。 - 闭包引用 :子应用内部闭包持有DOM或全局变量。
解决:避免在闭包中保存大对象,卸载时手动置空引用。
3. 预防措施
- 编写自动化测试:模拟子应用多次加载/卸载,监控内存变化。
- 使用
WeakMap
/WeakSet
存储临时数据,避免强引用导致无法回收。
58. 子应用加载失败时,如何进行错误捕获和降级处理?
子应用加载失败(如网络错误、资源损坏)需优雅降级,避免影响整个应用:
1. 错误捕获机制
-
Qiankun错误钩子 :通过
registerMicroApps
的error
回调捕获加载错误:javascriptregisterMicroApps( [ { name: 'app-vue', entry: '//invalid-url', ... } ], { error: (appName, err) => { console.error(`子应用${appName}加载失败:`, err); showErrorPage(appName); // 显示错误页面 } } );
-
全局错误监听 :捕获子应用运行时错误:
javascriptwindow.addEventListener('error', (err) => { if (err.target.src?.includes('app-vue')) { console.error('子应用资源加载失败:', err.target.src); } });
2. 降级处理方案
-
显示友好提示 :在子应用容器中展示错误信息:
javascriptfunction showErrorPage(appName) { const container = document.getElementById('app-container'); container.innerHTML = ` <div class="error-page"> <h3>抱歉,${appName}应用加载失败</h3> <button onclick="reloadApp('${appName}')">重试</button> </div> `; }
-
加载备用版本 :若当前版本失败,自动切换到历史稳定版本:
javascriptasync function reloadApp(appName) { const fallbackVersion = await getFallbackVersion(appName); // 获取备用版本 updateAppEntry(appName, `//cdn.example.com/${appName}/${fallbackVersion}/`); // 更新入口 loadMicroApp({ name: appName }); // 重新加载 }
-
跳转到独立应用 :若集成加载失败,引导用户访问子应用独立地址:
html<a href="https://app-vue.example.com" target="_blank"> 点击访问独立版${appName} </a>
59. 微前端中如何处理跨域问题?
子应用与基座若部署在不同域名下,会产生跨域问题(如资源加载、接口请求),解决方式:
1. 资源加载跨域(JS、CSS、图片)
-
CORS配置 :子应用服务器设置
Access-Control-Allow-Origin
允许基座域名:nginx# 子应用Nginx配置 location / { add_header Access-Control-Allow-Origin https://base.example.com; add_header Access-Control-Allow-Methods *; add_header Access-Control-Allow-Credentials true; }
-
CDN部署:将子应用资源部署到支持跨域的CDN,CDN默认配置允许所有域名访问。
2. 接口请求跨域
-
基座代理 :基座通过Webpack DevServer或Nginx代理子应用接口:
javascript// 基座vue.config.js(开发环境) module.exports = { devServer: { proxy: { '/api/app-vue': { target: 'https://app-vue.example.com', pathRewrite: { '^/api/app-vue': '/api' }, changeOrigin: true } } } };
-
子应用接口CORS :接口服务器设置跨域头,允许基座域名访问:
java// Java Spring Boot示例 @CrossOrigin(origins = "https://base.example.com", allowCredentials = "true") @RestController public class ApiController { ... }
3. iframe跨域通信(若使用iframe集成)
通过postMessage
实现跨域通信:
javascript
// 基座向子应用发送消息
const iframe = document.getElementById('app-iframe');
iframe.contentWindow.postMessage({ type: 'DATA', data: 'hello' }, 'https://app-vue.example.com');
// 子应用接收消息
window.addEventListener('message', (e) => {
if (e.origin === 'https://base.example.com') {
console.log('收到基座消息:', e.data);
}
});
60. 微前端项目中,如何调试子应用?
子应用调试需兼顾独立运行 和集成到基座两种场景,常用方法:
1. 独立调试
- 直接启动子应用开发服务器(如
npm run serve
),通过localhost:8080
访问,使用浏览器DevTools调试。 - 优势:调试环境纯净,不依赖基座,适合开发初期。
2. 集成到基座调试
-
本地代理 :将基座的子应用入口指向本地开发服务器:
javascript// 基座开发环境配置 registerMicroApps([ { name: 'app-vue', entry: '//localhost:8081', // 本地子应用开发服务 container: '#container', activeRule: '/vue' } ]);
-
源码映射(Source Map) :子应用构建时保留Source Map,便于在基座中定位源码:
javascript// 子应用vue.config.js module.exports = { configureWebpack: { devtool: 'source-map' // 生成Source Map } };
3. 框架特定调试工具
-
Vue子应用 :在基座中启用Vue DevTools,需确保子应用的Vue实例暴露到全局:
javascript// 子应用main.js if (process.env.NODE_ENV === 'development') { window.Vue = Vue; // 暴露Vue供DevTools识别 }
-
React子应用 :使用React DevTools,同样需确保
react
和react-dom
可被工具识别。
4. 日志与调试工具
-
在子应用中添加环境标识日志,区分独立/集成环境:
javascriptif (window.__POWERED_BY_QIANKUN__) { console.log('子应用运行在基座中'); } else { console.log('子应用独立运行'); }
-
使用
console.group
分组打印子应用日志,避免与基座混淆:javascriptconsole.group('app-vue'); console.log('组件渲染'); console.groupEnd();
5. 远程调试
- 若子应用已部署,通过远程Source Map(如上传到CDN)关联线上代码与本地源码,使用Chrome的"Overrides"功能替换线上资源为本地文件调试。
二、88道微前端面试题目录列表
文章序号 | 微前端面试题88道 |
---|---|
1 | 微前端面试题及详细答案88道(01-08) |
2 | 微前端面试题及详细答案88道(09-18) |
3 | 微前端面试题及详细答案88道(19-35) |
4 | 微前端面试题及详细答案88道(36-43) |
5 | 微前端面试题及详细答案88道(44-60) |
6 | 微前端面试题及详细答案88道(61-73) |
7 | 微前端面试题及详细答案88道(74-88) |