摘要(Auto)

  • 生成时间:2025-12-20
  • 简历中出现的项目标题(提取):大疆用户中心重构 / 大疆售后 RMS 系统重构 / 跨平台公告插件系统 / 大疆 DevOps 平台维护 / XDR 系统 - 魔方大屏 + 报表
  • 面试大纲关键词(提取 Top10):1)大疆用户中心重构:性能优化 + HTTP 原理 + Webpack 架构 / 性能指标与方法论 / 简历可落地点(结合你的“优化四板斧”) / HTTP 常考点(从“为什么变快”倒推) / Webpack 架构(工程化面试常考) / 按优化顺序,把方案“串起来”(排查 → 定位 → 选择 → 验证) / 0. 排查与基线(先把问题“量化”) / 1. 先保“可见”——骨架屏预渲染(直接拉低 LCP) / 2. 再减“阻塞”——关键渲染路径(CRP)梳理:CSS/字体/首图优先级 / 3. 再降“下载与解析成本”——更小的包体与更少的无效代码

建议追问(Auto)

  • 你为什么在该项目/场景里选择这个方案?替代方案为何不选?
  • 最大一次事故/踩坑是什么?如何定位与回滚?
  • 如果重做:架构/边界/工程化会怎么调整?

关联卡片

在我项目中的角色与使用场景

  • 典型场景:做“跨平台公告插件/SDK/组件库”这类要被外部系统集成的产物。
    • 目标:产物要小、格式要全(esm/cjs/umd)、tree-shaking 友好、外部依赖可控(external)。
  • 我在项目里的落地:
    • 设计多产物输出(ESM + CJS + UMD),并约定 exports 字段与类型声明输出。
    • 控制 breaking change:版本化、变更记录、以及验证“被集成方”的兼容性矩阵。

原理简述

Rollup 的核心优势是:以 ESM 为中心做静态分析,天然适合 tree-shaking 与高质量库产物。

  • 模块解析:对 ESM import/export 做静态分析,构建依赖图。
  • tree-shaking
    • 能删除“未被引用的导出”,前提是代码可静态分析且无副作用(side effects)。
    • 关键开关:treeshakemoduleSideEffects、以及 package.jsonsideEffects 声明。
  • external:库构建常把 react 这类依赖标记为外部,避免打进产物导致重复依赖与体积膨胀。
  • 插件体系:同样有 transform/resolve/load/generateBundle 等生命周期,生态成熟。

权衡点:

  • Rollup 不以 Dev Server/HMR 为核心;做应用构建往往需要更多配套。
  • 对 CJS/动态 require 的处理,需要插件与约束(尽量写成 ESM)。

对比表格

维度RollupWebpackVite
最适合库/SDK应用(全能)应用(DX 优先)
tree-shaking(ESM 优先)依赖配置与写法生产同 Rollup
external 控制强(库场景友好)也可做,但更偏应用可做
多格式输出一等公民可做但较繁琐生产可做(Rollup)

我的选型口径:

  • “被别人引入”的库:优先 Rollup(产物质量、体积、格式完整)。
  • “自己运行”的应用:Webpack/Vite 更合适。

模拟问答

  • [ ] Q1:tree-shaking 为什么有时不生效?
    • 常见原因:
      • 产物是 CJS(静态分析弱),或混用了动态 require
      • 包声明有副作用(未正确配置 sideEffects),Rollup 不敢删。
      • 写法导致引用不可静态确定(比如 export * + 动态访问)。
    • 解决:保持 ESM、配置 moduleSideEffects、把副作用代码(polyfill/全局注入)显式隔离。
  • [ ] Q2:为什么库构建要 external?
    • 避免把 react/lodash 打进包导致重复依赖、版本冲突与体积膨胀;
    • 让使用方用自己的依赖版本,符合生态预期。

手写代码区

一个“ESM + CJS 双产物 + external + d.ts”思路示例:

import typescript from '@rollup/plugin-typescript'

/** @type {import('rollup').RollupOptions} */
export default {
  input: 'src/index.ts',
  external: ['react', 'react-dom'],
  plugins: [
    typescript({
      tsconfig: './tsconfig.json',
      declaration: true,
      declarationDir: 'dist/types',
      rootDir: 'src'
    })
  ],
  output: [
    { file: 'dist/index.mjs', format: 'esm', sourcemap: true },
    { file: 'dist/index.cjs', format: 'cjs', sourcemap: true, exports: 'named' }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

我的补充(Manual)

(不会被脚本覆盖:踩坑、细节、反例、排查路径)

复盘与反思(Learnings)

  • 如果重做会怎么改?

面试官追问(面试官视角)

  • [ ] 为什么选这个方案?替代方案为什么不选?
  • [!] 最大一次事故/踩坑是什么?如何定位与回滚?
  • [ ] 如果重做会怎么改?
上次更新:
(adsbygoogle = window.adsbygoogle || []).push({});