牛客字节基础架构前端暑期实习面经整理(pnpm / Monorepo / 构建)(十九)
收录日期:2026-05-06
关键词:前端、工程化、pnpm、yarn/npm、Monorepo、依赖管理、打包流程、React Hooks
1. npm 生命周期是什么?常见钩子有哪些?
参考答案
- 生命周期是指在
pnpm/npm/yarn执行 install、publish、version 等阶段会触发的一系列脚本钩子。 - 常见:
preinstall/install/postinstallprepare(常用于构建产物、husky 安装;对本地和 git 安装都可能触发)prepublishOnly(发布前)
- 风险:
postinstall易引入供应链风险与不可重复构建;尽量最小化。
2. pnpm 和 yarn/npm 的核心差异?
参考答案
- pnpm 使用 content-addressable store(全局内容寻址)+ 硬链接/符号链接,节省磁盘与安装时间。
- 默认更“严格”(non-flat):
- 依赖不会被无脑提升到顶层,能更早暴露“幽灵依赖”问题。
- workspace/monorepo 体验好:link-workspace-packages、filter、hoist 策略可控。
3. Monorepo 下 package 引用方式是什么?node_modules 里会出现吗?
参考答案
- workspace 包引用通常写成:
"@scope/pkg": "workspace:*"(或workspace:^等)
- 安装后:
- pnpm 会把 workspace 包以链接的形式挂到依赖树中;
node_modules里看到的是链接/虚拟 store 结构,不是传统扁平展开。
- pnpm 会把 workspace 包以链接的形式挂到依赖树中;
- 关键点:保证 TS path、构建产物(types/exports)、以及包的
exports字段正确。
4. pnpm 如何管理依赖版本?出现不同依赖组合怎么办?
参考答案
- 锁文件:
pnpm-lock.yaml固化解析结果,确保可复现。 - 多版本共存:pnpm 允许在不同子树安装不同版本(隔离),避免互相覆盖。
- 版本统一策略:
- 用
overrides统一某些依赖版本; - 用 workspace 约束(例如统一 react/react-dom);
- CI 校验(duplicate/semver drift)。
- 用
5. 依赖存在多个版本都会打包吗?运行时会冲突吗?
参考答案
- “会不会打包”取决于打包器的依赖解析与最终引用路径:
- 若不同子包各自引用了不同版本且都被打入同一产物,可能出现重复代码。
- “会不会冲突”取决于包类型:
- 单例要求强(react、vue、一些 runtime 单例库)多版本常会出问题(Hooks 失效、上下文不共享)。
- 工具库(lodash、dayjs)多版本一般只是包体增大。
- 实践:把单例依赖提升为根依赖并锁定版本;对外部依赖用
peerDependencies+ bundler external(库开发场景)。
6. 如何锁定依赖版本?
参考答案
- 使用锁文件提交到仓库;CI 强制
--frozen-lockfile。 - 精确版本(不使用
^/~)或配合pnpm config控制。 - 对关键依赖用
overrides/resolutions(yarn)做强制对齐。
7. 构建工具打包的过程(高层)?
参考答案
- 入口解析 → 模块图构建(解析 import/require)→ 转译(TS/JSX)→ 依赖收集与 tree-shaking → code splitting → 产物生成(chunk)→ 压缩与 sourcemap → 输出到 dist。
- Vite 开发阶段偏“按需加载 + 快速转译”,生产阶段仍以 Rollup 打包为主。
8. 适合 pnpm 的分包/拆包策略?
参考答案
- 应用侧:路由级拆包 + 大组件懒加载;公共依赖拆 vendor(注意缓存与更新频率)。
- Monorepo:按领域拆 package(ui/data/utils),明确依赖方向(避免循环)。
- 约束:对单例依赖统一版本;对可选依赖避免在多个包重复引入导致体积膨胀。
9. 写一个 usePrevious Hook,并解释原理
参考答案
思路:用 useRef 存“上一次值”,在 useEffect 里更新。
useRef的.current跨渲染持久,但更新不会触发重新渲染。useEffect在 commit 后执行,因此能在下一次 render 前保存“上一次”的值。