ATRULE 技术博客ATRULE 技术博客
首页
博客
文档
关于
首页
博客
文档
关于
  • 技术文章

    • VuePress 2.x 完全指南
    • Gemini3 & GPT5 & DeepSeek3:AI时代程序员的身份转变
    • Agent 架构选型指南:单智能体 vs 多智能体
    • Agent 工程师转型学习路线图 (Full-Stack to Agent Engineer)
    • Agent 工程师学习笔记
    • 📖 Agent 系统架构与工程实践面试速记卡片
    • Agent 流式对话前端踩坑记录
    • RAG 检索工程问题记录
    • Agent 后端问题记录(Koa / MongoDB)
    • LLM 调用与 Agent 编排问题记录
    • Electron 桌面端问题排查记录
    • AI Agent 全栈开发问题排查记录
    • ES2026 与 TypeScript 进阶问题记录
    • 浏览器渲染与 V8 内存问题记录
    • React 19 与 Vue 4 新内核问题记录
    • 前端工程化与微前端问题记录
    • 性能、安全与可观测性问题记录
    • 前端架构实战问题记录
  • 项目实战

    • Node.js + Koa 抖音直播弹幕Agent 五大核心模块(面试项目完整版,TS技术栈)★★★★★
    • Poiclaw 项目蓝图:自主编程实体
    • AI旅行助手

前端工程化与微前端问题记录

记录构建工具链、Monorepo、Module Federation 落地时踩过的坑,每个问题都是实际遇到过并解决掉的。

问题一:"本地好的线上坏"

现象:循环依赖的模块级单例在 dev 下初始化一次,prod 下初始化两次。

原因:Vite 双引擎分叉——dev 用 esbuild 预构建(按需 ESM)、prod 用 rollup 打包,两者代码分割策略和循环依赖执行顺序不同;CJS 互操作(default 导出)处理也有差异。

解决:治本靠单引擎统一语义(Vite 6+ Rolldown,与 rollup API 兼容);治标是 CI 加 prod build 后冒烟测试 + ESLint import 规则禁循环依赖。长期修复是消除循环而不是锁定执行顺序——顺序锁只是把炸弹换个位置。

问题二:8000 模块仓库 Vite 冷启动 2 分钟

现象:monorepo 冷启动主要耗在依赖预构建,CI 上每次都要重跑。

原因:预构建缓存(node_modules/.vite)在 lockfile/config 变化时全量失效;bundleless 路线深层依赖还有运行时级联请求瀑布。

解决:CI 缓存预构建产物(key = lockfile hash + vite config hash);大型应用改用惰性构建 + 持久缓存的 bundler 路线(Turbopack/Rspack 只编译当前路由触达的模块,模块图按需构建、HMR 精确失效)。

问题三:改一个底层包,CI 全仓库跑一遍

现象:100 个包的 monorepo,改一个工具包,CI 跑了 40 分钟。

原因:没配置任务依赖图,所有包无条件构建测试。

解决:Turborepo 按 dependsOn: ["^build"] 拓扑执行(^ = 先构建上游),输入 hash(源码+依赖声明+lockfile+环境变量)命中缓存直接回放产物——"只测受影响的" = 图上被标记脏的子树:

{ "tasks": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] } } }

版本发布用 Changesets:底层包 minor bump,workspace 内依赖它的包递归自动 bump。循环依赖在 merge 前用 CI 检测拦住(turbo 任务图会直接报环)。

问题四:MF 远程组件把宿主页拖白屏

现象:Module Federation 的 remote CDN 挂了,host 页面白屏等死。

原因:remote 动态加载没有超时和降级;shared singleton 协商失败也没 fail fast,静默跑出双 React 实例。

解决:

async function loadRemote<T>(loader: () => Promise<T>, fallback: () => T): Promise<T> {
  try {
    return await Promise.race([
      loader(),
      new Promise<never>((_, reject) => setTimeout(() => reject(new Error('timeout')), 5000)),
    ]);
  } catch (err) {
    report(err);
    return fallback(); // 本地兜底组件,remote 挂了不白屏
  }
}

版本治理:react/vue 等核心库全部 singleton: true + requiredVersion + strictVersion(协商不满足宁可报错,双实例 Hooks 必炸);工具库放开 singleton 多实例。类型靠 MF 2.0 构建时产出 d.ts 给 host 消费,不发包。

问题五:子应用卸载后定时器还在跑

现象:qiankun 子应用卸载后,第三方 SDK 的定时器和事件监听还在执行,内存持续上涨。

原因:Proxy 沙箱只代理 window 读写,addEventListener/setInterval 靠补丁劫持复原——第三方 SDK 缓存了原始函数引用的就逃逸;样式污染更是另一个治理层,JS 沙箱救不了。

解决:SDK 层强制副作用收集器——mount 时记录新增监听器/定时器/全局变量,unmount 统一清理;样式用 scoping 前缀(Shadow DOM 隔离最强但弹窗挂 body 就穿)。新项目大方向是 Isolated Micro Frontends(浏览器原生隔离),牺牲共享性换真隔离。

延伸:第三方 SDK 缓存 window.fetch 原始引用的缓存逃逸没有完美解,只能白名单审计 + 沙箱补丁尽量收口。

Prev
React 19 与 Vue 4 新内核问题记录
Next
性能、安全与可观测性问题记录