前端知识速查

一、七条技能

text 复制代码
HTML / CSS / JavaScript
  ↓ 形成浏览器可执行的页面
React / Vue
  ↓ 用组件和状态描述 UI
Redux / Zustand / Pinia
  ↓ 管理跨组件、跨模块或高频状态
Next.js / Vite / Webpack
  ↓ 负责开发、编译、分包、SSR 与构建产物
浏览器 / HTTP / 缓存 / 渲染
  ↓ 决定首屏与交互性能
WebView / JSBridge / SDK
  ↓ 把 H5 接入客户端能力
DevTools / Whistle / ADB / 日志
  ↓ 证明问题发生在哪一层
测试 / 发布 / 监控 / 复盘
  ↓ 保证变更可交付、可验证、可沉淀
Agent / Skill / Harness
  ↓ 放大上述工程能力,但不能替代判断与验证

二、用户操作视角

text 复制代码
用户操作
→ DOM 事件或路由
→ React/Vue 业务逻辑
→ Store 状态变化
→ 浏览器或 Native 网络请求
→ 后端响应
→ 数据清洗与状态派生
→ 组件重新渲染
→ 图片/字体等资源加载
→ 浏览器布局、绘制、合成
→ 用户最终看到结果

三、HTML5 / CSS3 / JavaScript

3.1 主线

HTML 描述内容结构,CSS 负责布局和视觉,JavaScript 负责状态、行为和异步;框架最终仍然落到 DOM、CSSOM、事件与浏览器渲染流水线。

3.2 HTML 语义化

语义化不是"少写 div",而是让元素表达内容角色:

  • 页面地标:header、nav、main、aside、footer;
  • 独立内容:article;
  • 有主题的一组内容:section,通常应有标题;
  • 操作使用 button,导航使用 a,不要用可点击的 div 冒充;
  • 表单输入用 label 关联控件,图片提供合适的 alt;
  • 标题按信息层级组织,不因字号需要乱跳级。

收益是可访问性、SEO、键盘操作、默认交互语义和可维护性。需要强调:语义化不等于自动获得好 SEO;内容质量、渲染方式、元数据和可抓取性同样重要。App WebView 内部页面通常不以 SEO 为核心目标,但语义化仍有可访问性和维护价值。

3.3 盒模型、布局与响应式

盒模型:

text 复制代码
content → padding → border → margin
  • content-box:声明宽度只计算 content;
  • border-box:声明宽度包含 content、padding、border,业务布局通常更直观;
  • 全局常见设置:*, *::before, *::after { box-sizing: border-box; }。

Flex 与 Grid:

  • Flex 是一维布局,适合导航、工具栏、单方向列表与对齐;
  • Grid 是二维布局,适合同时控制行列的页面骨架或卡片网格;
  • min-width: 0 是 Flex 子项文本省略经常遗漏的点;
  • flex: 1 常等价于 1 1 0%,不是简单的"宽度占满";
  • 收缩权重与 flex-shrink × flex-basis 有关。

响应式要同时考虑:

  1. 视口:正确设置 viewport;
  2. 布局:Flex/Grid、百分比、minmax();
  3. 尺寸:rem、vw、dvh 与必要的 px;
  4. 断点:媒体查询或容器查询;
  5. 内容:长文本、国际化、图片比例与安全区;
  6. 输入方式:触摸热区、hover 不可用、键盘与无障碍;
  7. WebView:状态栏、安全区、软键盘、横竖屏和不同内核版本。

3.4 BFC 与层叠上下文

  • BFC 主要影响块级布局、浮动、外边距合并;
  • stacking context 决定 z 轴上的分组与比较范围;
  • z-index: 99999 仍可能被遮挡,因为后代无法越过祖先层叠上下文。

案例:低代码组件弹窗被宿主组件遮挡。静态代码中弹窗已经 position: fixed; z-index: 999,运行时沿祖先链发现宿主的 position + z-index 创建了层叠上下文。最终通过 Portal 把弹窗挂到 document.body,脱离原层叠上下文。这个案例体现的是 CSS 原理、组件宿主边界和运行时取证,而不是"把 z-index 调大"。

3.5 JavaScript 主干

Event Loop 标准答法:

JavaScript 执行当前同步调用栈;栈清空后先持续清空微任务队列,再由事件循环选择下一个 Task,浏览器会在合适时机执行渲染。Promise 回调属于微任务,setTimeout 回调属于 Task。渲染不是简单地固定发生在每个宏任务之后,而由浏览器调度。

竞态要点:Promise 解决"等待异步结果",不自动保证"最后意图获胜"。排行榜项目中,用户快速切换时间和地区时,旧请求可能后返回并覆盖新结果。需要把用户意图编码进请求:

js 复制代码
let latestRequestId = 0;

async function loadList(filters) {
  const requestId = ++latestRequestId;
  const data = await fetchList(filters);
  if (requestId !== latestRequestId) return;
  render(data);
}

如果底层支持 AbortController,还可以取消旧请求以节省资源;即便取消失败,响应提交前仍应校验 requestId 或筛选上下文。


四、React / Redux / Zustand / Next.js / Vue 3

4.1 React:从状态到 DOM 的完整链路

一句话:React 让开发者声明 UI = f(state);更新状态后,React 调度 render,生成新的元素树并协调差异,最后在 commit 阶段修改 DOM 和执行相关副作用。

要能区分:

  • render 阶段:计算 UI,可被打断或重做,不应产生外部副作用;
  • commit 阶段:提交 DOM 变更;
  • useEffect:在 commit 后调度,通常不会阻塞浏览器绘制,适合订阅、请求等;具体是否在绘制前后执行会受交互更新等因素影响,不应用它做必须在首帧前完成的布局修正;
  • useLayoutEffect:DOM 提交后、浏览器绘制前同步执行,适合必须先测量再修正的布局;
  • 每次函数组件执行都有独立 props/state 快照,回调会通过闭包捕获某一轮快照;
  • setState 是请求更新,不是原地修改当前 render 中的变量;
  • key 表示列表项的稳定身份,不是消除 warning 的装饰。

性能 API 要说清"缓存什么"和"何时值得":

  • React.memo:在父组件更新时,基于 props 比较决定是否跳过子组件 render;
  • useMemo:缓存一次计算结果或引用;
  • useCallback:缓存函数引用;
  • 它们都有比较和内存成本,只有计算较重、引用稳定性影响 memo 子组件、或依赖链确实需要时才使用。

项目案例:时间轴的 currentTime 高频变化,时间轴头部只订阅 canUndo/canRedo;轨道项通过 Zustand selector、React.memo 和稳定 props 隔离渲染,拖拽位置则由 react-spring 直接更新 transform,避免每帧都走 React render/diff/commit。

4.2 Redux:可预测的集中状态

Redux 核心不是"全局变量",而是:

text 复制代码
dispatch(action)
→ reducer(previousState, action)
→ newState
→ selector 读取切片
→ 订阅组件更新

适合状态关系复杂、更新需要追踪、多人协作需要明确约束的场景。避免把所有局部 UI 状态都塞入 Redux。

项目案例:首页在 getServerSideProps 中取得用户、会员和配置数据,服务端 dispatch 到 Redux;next-redux-wrapper 将快照写入 __NEXT_DATA__,浏览器恢复 store,reducer 处理 HYDRATE 合并服务端状态,再由 Provider 提供给组件树。一次性页面数据走 pageProps,需要响应式共享的数据走 Redux。

追问:为什么 reducer 要保持纯函数和不可变更新?

相同输入得到相同输出,便于回放、测试和调试;新引用也让订阅层能通过引用比较判断变化。直接修改旧对象会让变化边界不清晰,可能导致组件不更新或历史状态被污染。

4.3 Zustand:外部 Store 与精准订阅

Zustand store 可以理解为 React 外部的状态容器:内部保存状态并维护订阅者,React Hook 通过 selector 订阅切片,非 React 类可用 getState/setState。

  • selector 返回基本值时,默认用 Object.is 比较新旧结果;
  • selector 每次返回新对象时,即使字段相同也会被认为变化;
  • 需要 useShallow、自定义 equality function,或分别订阅基本字段,才能获得浅比较效果;
  • 不应把 Object.is 叫"浅比较"。

项目案例: Controller/Manager 是非 React 类,通过 store 的 getState/setState 与 UI 协作;组件只订阅所需字段,避免 60Hz 播放时间更新带动无关工具栏重渲染。这也解释了为什么选 Zustand:API 小、外部访问自然、适合连接 React UI 与命令/控制器对象。

4.4 Redux、Zustand、Context 怎么选

方案 更适合 主要风险
组件 state 单组件或局部子树 提升过高会让更新范围扩大
Context 低频、跨层级依赖,如主题/用户环境 Provider value 变化会使消费者更新,拆分不当易扩大影响
Zustand 轻量共享状态、外部类、高频切片订阅 store 边界随意、selector 返回值不稳定
Redux 复杂业务状态、严格事件流、可追踪更新、SSR 生态 样板与建模成本,不应承载所有瞬时 UI 状态

回答选型时先说数据的所有者、生命周期、更新频率和消费范围,不要先站框架阵营。

4.5 Next.js:渲染策略与 Hydration

必须分清:

  • CSR:服务端给壳,客户端加载 JS 后请求数据并渲染;
  • SSR:每次请求在服务端生成 HTML;
  • SSG:构建期生成 HTML;
  • ISR:静态页面按策略增量再生成;
  • Hydration:客户端 React 在服务端已有 DOM 上恢复组件状态和事件能力。

Hydration mismatch 的本质:服务端首次输出与客户端首次 render 不一致。常见原因包括 Date.now()、Math.random()、只在浏览器存在的 API、时区/语言差异和首轮读取 localStorage。

项目案例:使用 Next.js Pages Router。请求到达自定义 server 后匹配页面,getServerSideProps 读取 header/query 和平台配置,并发请求上游,初始化 Redux,服务端生成 HTML;浏览器加载 _next 的 JS/CSS 后 hydration。项目还有 SSR 直出、客户端渐进渲染和 CSR 降级路径。

4.6 Vue 3:与 React 对照理解

Vue 3 的核心是响应式依赖追踪:读取响应式值时收集依赖,写入时触发相关 effect/组件更新。Composition API 用 ref/reactive/computed/watch 组织逻辑。

与 React 的差异不要背成优劣:

  • React 更强调每次 render 的快照和显式依赖;
  • Vue 通过 Proxy/Ref 做细粒度依赖追踪,模板由编译器提供优化信息;
  • React Hook 依赖调用顺序,Vue Composition API 没有相同限制;
  • Pinia 与 Zustand 都轻量,但 Pinia 深度融入 Vue 响应式、DevTools 和插件体系。

项目案例:使用 Vue 3 + Vite + Pinia,把上传、处理中、完成、异常等状态集中在 task store;异步 action 串联上传、推理和结果获取,组件根据状态显示骨架屏、结果或错误。使用 URL.createObjectURL 做本地预览,文件变化或组件销毁时 revokeObjectURL 防止泄漏。


五、Vite / Webpack / 发布上线

5.1 一句话主线

开发工具解决模块解析、语法转换、依赖预构建和热更新;生产构建把模块图转换为可缓存、可分包、可部署的产物;发布流程保证 HTML、JS/CSS 资源、服务容器和环境配置来自同一版本。

5.2 Webpack 原理

text 复制代码
entry
→ 解析模块与依赖
→ Loader 转换非标准模块或源码
→ 形成 Module Graph
→ 按入口和动态导入形成 Chunk Graph
→ 优化、Tree Shaking、压缩
→ emit assets
  • Loader 面向单个模块内容转换,例如 Babel、CSS、图片;
  • Plugin 监听构建生命周期 hooks,影响打包、优化、资源生成等更广流程;
  • Module 是源码依赖单元,Chunk 是打包过程中的代码块,Bundle/asset 是最终文件;
  • 动态 import() 是常见分包边界;
  • Tree Shaking 依赖 ESM 的静态结构、副作用标记和构建器优化,不是"用了 import 就一定删干净"。

5.3 Vite 原理

开发阶段:

text 复制代码
浏览器原生 ESM 请求
→ Vite 按 URL 解析模块
→ 按需转换源码
→ 依赖预构建
→ 返回模块
→ 文件变化后通过 HMR 更新受影响模块

生产阶段:当前项目材料中的 Vite 版本以 Rollup 生成优化产物。

Vite 快的原因不是"完全不打包":开发时不先把整个业务打成一个 bundle,并对依赖预构建;生产仍然要构建、分包和压缩。

项目证据:配置了路径 alias、FFmpeg 预构建排除、构建 target、manualChunks、生产移除调试语句、全局常量和开发代理;FFmpeg 独立分包避免进入首屏主 chunk。

5.4 Babel、SWC 与 Polyfill

  • Babel/SWC 可以把 JSX、TypeScript 或新语法转换为目标 JavaScript;
  • 语法转换不等于补齐运行时 API;旧环境缺少 Promise、Array.from 等仍可能需要 polyfill;
  • Browserslist/target 描述目标环境,决定转译和兼容策略;
  • 项目选择 esnext 是明确放弃旧浏览器兼容以换取更小产物和更快构建,只适合环境受控的内部平台。

5.5 发布链路:必须讲清版本一致性

text 复制代码
本地开发与自测
→ push 代码
→ CI/容器内安装依赖并执行 Next SSR build
→ escheck 等产物兼容检查
→ 同步 _next 静态资源并生成静态资源 tag
→ 产出 SSR 容器镜像
→ K8s 预发布部署
→ 发布与容器匹配的静态资源 tag
→ Whistle 配置域名/Host 验收
→ 测试流程与线上发布

关键风险:容器 tag 与静态资源 tag 不一致,会导致 HTML 引用的 _next hash 资源不存在或版本错配。验收不能只看首页打开,还要检查资源 404、接口环境、登录态、缓存、端内 WebView 和降级路径。


六、浏览器渲染与性能优化

6.1 URL 到页面

text 复制代码
URL 解析
→ 缓存与 DNS
→ 建立连接(TCP/TLS 或 QUIC)
→ HTTP 请求/响应
→ HTML 流式解析生成 DOM
→ CSS 解析生成 CSSOM
→ 样式计算与渲染树
→ Layout
→ Paint
→ Composite
→ JS 框架 hydration/交互

注意:解析 HTML 时遇到普通同步 script 可能阻塞;defer 在解析后按顺序执行,async 下载完即执行、顺序不保证。CSS 通常不阻塞 DOM 构建,但会影响渲染,也可能间接阻塞依赖样式信息的脚本。

6.2 Layout、Paint、Composite

  • 改变几何尺寸或位置可能触发布局;
  • 颜色、阴影等可能只需绘制;
  • transform/opacity 在满足分层条件时可主要由合成阶段处理;
  • 强制同步布局常来自"写样式后立刻读 offsetWidth/getBoundingClientRect"的读写交错;
  • will-change 不是越多越好,图层会消耗内存。

拖拽用 transform 和动画值直接更新,目标就是避开高频 React 更新及昂贵布局;应使用 Performance 和 React Profiler 证明,而不是仅凭"感觉顺滑"。

6.3 首屏优化要按指标拆

先明确优化对象:

  • TTFB:服务端响应速度;
  • FCP:首次内容出现;
  • LCP:最大内容元素完成渲染;
  • CLS:布局稳定性;
  • INP:交互响应;
  • JS 执行与 hydration 成本。

优化手段与问题对应:

问题 方案
HTML 到得晚 CDN/缓存、服务端优化、SSR 上游并发与超时
主包太大 路由/组件分包、Tree Shaking、按需引入、移出重型依赖
关键资源晚 正确使用 preload、preconnect、fetchpriority,优化请求优先级
非关键资源抢带宽 lazy、动态 import、低优先级加载
图片拖慢 LCP 尺寸和格式优化、响应式图片、首屏图不要懒加载
hydration 太重 减少首屏客户端 JS、延迟非关键交互、合理 SSR/SSG
页面跳动 预留图片/广告尺寸、稳定字体与骨架结构

6.4 lazy、preload、prefetch 的边界

  • loading="lazy":元素接近视口再加载,适合非首屏图片/iframe;
  • 动态 import():执行到边界时加载代码 chunk;
  • preload:当前页面很快必需的高优先级资源;滥用会抢占关键带宽;
  • prefetch:未来可能使用、低优先级获取;
  • preconnect:提前建立跨域连接;
  • 首屏 LCP 图片通常不应 lazy,应让浏览器尽早发现并正确设置尺寸/优先级。

项目案例:对非首屏弹窗/模块做动态加载并分阶段渲染; 用组件库按需引入、路由拆分和本地 Blob URL 预览;把 FFmpeg 单独分包。只有实际配置过 preload/prefetch 才说"做过资源预加载"。

6.5 性能验证闭环

text 复制代码
建立基线
→ Performance/Network/React Profiler 定位瓶颈
→ 提出单一假设
→ 修改
→ 相同设备、网络和操作复测
→ 对比指标与火焰图
→ 检查功能和内存回归

项目中可讲:时间轴观察 commit 次数、Frames、Long Task、heap;会员中心用网络限速、首帧录像、资源 onLoad 与状态日志验证白屏/闪烁时序。


七、前后端联调与 DevTools / Whistle / ADB 排障

7.1 通用排障框架

text 复制代码
1. 定义现象:谁、在哪个环境、什么操作、期望与实际是什么
2. 稳定复现:记录版本、账号、网络、设备和时间
3. 画链路:操作 → 请求 → 响应 → 状态 → DOM → 资源 → 可见结果
4. 分层取证:Network、Console、React/Vue DevTools、Performance、Bridge/客户端日志
5. 提出最小假设并用 Mock/断点/日志证伪
6. 修复后在原条件和边界条件下回归
7. 记录根因、边界、证据和预防措施

7.2 三个工具各自解决什么

  • DevTools:DOM/样式、浏览器发出的请求、JS 断点、性能、内存、存储;
  • Whistle:作为代理观察或改写请求响应、Host 映射、Mock、Rewrite、弱网与异常场景;HTTPS 解密依赖调试设备主动信任 CA;
  • ADB:开发机到 Android 设备的调试通道,可看设备、日志、shell、端口转发并辅助 WebView 调试。ADB 本身不是抓包工具。

必须先判断请求由谁发出:浏览器 XHR/fetch 可在 Network 中看到;通过 CMD 186 走 Native 网络通道时,浏览器 Network 可能没有记录,需要 Bridge 日志、客户端日志或代理抓包。

7.5 接口联调基本功

要主动核对:

  • method、URL、query/body、Content-Type;
  • token/cookie/header 与签名;
  • HTTP 状态和业务 code 的区别;
  • 空数据、字段缺失、类型漂移、超时和重复提交;
  • 幂等、重试、取消与竞态;
  • CORS 只由服务端响应许可,开发代理是开发期规避同源限制,不等于生产 CORS 已解决;
  • 以服务端权威状态判断支付成功,不能用"点击过按钮"代替。

八、WebView / JSBridge / 客户端命令号

8.1 一句话主线

WebView 是 App 内嵌的 Web 运行环境;JSBridge 是 H5 与 Native 约定的方法、参数、回调和传输通道;命令号是协议中的能力标识,不是前端随意生成的编号。

8.2 调用链

text 复制代码
H5 business code
→ mobileCall(cmd, params, callback)
→ SDK 序列化 cmd / jsonStr / callbackName
→ 注入对象、自定义 Scheme 或 postMessage
→ Native 拦截并按 cmd 路由
→ 执行登录、支付、播放等原生能力
→ Native 按 callbackName 回调 H5
→ SDK 解码、解析、清理 callback
→ Promise/callback 回到业务层

项目中的 Android 新通道会构造 jsbridge:// Scheme 并用隐藏 iframe 触发;旧通道可能调用 external.superCall;iframe 内页面先 postMessage 给父页面转发。当前仓库只能证明 H5 SDK 侧,不能据此声称实现过 Native 拦截器。

8.3 稳健接入要处理什么

  • 端内/端外,Android/iOS;
  • 客户端版本与命令支持矩阵;
  • 参数序列化与字段差异;
  • callbackId 唯一性、一次性清理和重复回调;
  • 超时、取消、页面卸载和降级;
  • iframe 消息的 origin/source 校验;
  • Native 收到命令不等于业务成功,最终状态应以明确回调或服务端结果为准;
  • 不把内部 SDK 能力说成个人从零实现。

8.4 项目案例:MV 播放与活动支付

MV 播放:先用命令号获取网络状态,再通过 Request/CMD 186 或 XHR 获取播放地址,按客户端版本选择播放命令;没有可靠结果回调的命令通过超时降级到 H5 页面。排障时不能只盯浏览器 Network。

活动支付:页面 EventEmitter 打开确认弹窗,VOO SDK 发出支付事件,支付组件调用 Native,成功/失败事件回到页面后再刷新用户、商品或装扮状态。页面事件、SDK 事件和 Native 结果必须分层,点击购买不代表支付成功。


九、Agent / Skill / Harness 与 AI Coding

9.1 概念关系

  • LLM:根据上下文生成下一步输出;
  • Tool:有明确输入输出的外部能力;
  • Agent Loop:模型决策、调用工具、观察结果并继续的循环;
  • Skill:可复用的程序性知识/SOP,说明何时做什么、读哪些参考、完成条件是什么;
  • References/Knowledge:字段、规则、事实、例外与示例;
  • Hook:在工具调用前后观察、记录、提醒或阻断;
  • Checkpoint:持久化可恢复状态;
  • Harness:把模型、上下文、工具、权限、状态、验证、观测和人机协作组合起来的运行环境。

一句话区分:Prompt 告诉模型"这次怎么做";Skill 固化可复用流程;Tool 真正执行能力;Harness 保证整个执行系统能受控运行。

9.3 AI Coding 的正确闭环

text 复制代码
任务契约
→ 提供最小必要项目上下文
→ 让 AI 先追踪真实数据流
→ 人确认方案与风险
→ 小步实现
→ lint / typecheck / test / build
→ Mock、日志或运行时验证
→ 审查 diff 与行为边界
→ 写回稳定知识和故障复盘

AI 输出需要检查:

  • 是否引用了真实文件、接口和字段;
  • 是否扩大需求或改动无关代码;
  • 是否破坏状态不变量、错误处理和兼容性;
  • 是否编造测试结果;
  • 是否在关键副作用前请求确认;
  • 是否用可观测证据证明最终行为。

十、工程质量、可维护代码与组件复用

10.1 质量不是"写了测试"四个字

text 复制代码
需求澄清
→ 状态与边界建模
→ 类型/接口契约
→ 小职责组件和纯数据转换
→ 错误、超时、取消、幂等与降级
→ 静态检查、单元/集成/E2E
→ 构建和兼容检查
→ 预发布/真机/灰度验证
→ 监控、回滚与复盘

10.2 状态建模优于布尔堆叠

多个布尔值容易产生非法组合:loading=true、success=true、error=true。优先用可辨识状态:

ts 复制代码
type TaskState =
  | { status: 'idle' }
  | { status: 'uploading'; progress: number }
  | { status: 'processing'; taskId: string }
  | { status: 'success'; result: Result }
  | { status: 'error'; message: string; retryable: boolean };

10.3 组件复用的判断标准

可复用组件应有:

  • 单一、稳定的业务职责;
  • 明确 props/事件契约;
  • 数据与视图解耦,原始接口字段先转为 view model;
  • 样式和宿主边界明确;
  • loading/empty/error/disabled 等状态完整;
  • 可配置但不做"万能组件";
  • 关键交互可测试、可观测

10.4 错误分层

  • 网络层:断网、DNS、超时、连接失败;
  • HTTP 层:4xx/5xx;
  • 协议层:响应结构不合法、字段缺失;
  • 业务层:库存不足、次数耗尽、未登录;
  • UI 层:渲染异常、资源加载失败;
  • 跨端层:Bridge 不存在、版本不支持、回调超时;
  • Agent 层:工具失败、流程偏离、证据不足、输出未通过校验。

不同层的重试和提示不同。支付/提交类操作重试前必须考虑幂等,不能把所有错误都自动重试。

相关推荐
雪芽蓝域zzs1 小时前
从零搭建【pnpm+Vue3+TS+Setup+VueRouter4+Pinia+Axios+ElementPlus (unplugin 按需)】仿若依后台
前端·vue.js
燕落南枝1 小时前
HTML 列表标签详解:有序列表、无序列表与描述列表
前端·html
派小心.2 小时前
DAU和MAU怎么计算?先确定活跃事件、用户键和统计窗口
大数据·服务器·前端·人工智能·数据分析
代码猎人2 小时前
前端怎么配合后端完成bug修复
前端
叫我铁汁儿吧2 小时前
JS作用域
前端·面试
定栓2 小时前
Webpack迁到Vite第七节(四):全家桶移除 — 保留项、脚本与数据收尾
前端·webpack·node.js
代码猎人2 小时前
前端怎么优化首屏加载速度
前端
代码猎人2 小时前
前端怎么保障项目稳定上线与运行
前端
数据掘金2 小时前
小程序埋点方案的埋点文档怎么自动生成?
前端