--- id: frontend.webpack.interview title: webpack 面试题 type: interview domain: frontend stack: [webpack] tags: [webpack, loader, plugin, tree shaking, 面试] level: intermediate related: [frontend.webpack.build-optimization, frontend.vite.interview] week: [7, 16] --- # webpack 面试题 ## 基础 ### 【基础】loader 和 plugin 有什么区别? **参考答案**:loader 负责把某类文件转换成 webpack 能处理的 JS 模块,本质是转换函数,在 `module.rules` 中配置;plugin 通过钩子介入整个编译生命周期,做打包优化、资源管理、注入环境变量等,在 `plugins` 中配置。 **追问**:多个 loader 的执行顺序?→ 从右到左(数组从后往前);每个 loader 还有 pitch 阶段,从左到右执行。 ### 【基础】hash、chunkhash、contenthash 的区别? **参考答案**:hash 与整次构建相关,任何改动都会变;chunkhash 与所在 chunk 相关;contenthash 与文件内容相关,最适合长期缓存(例如 CSS 文件不随 JS 变化)。 **追问**:只改了业务代码,vendor 的文件名也变了,为什么?→ 运行时代码或模块 id 混在 vendor 中;用 `runtimeChunk: "single"` 并使用确定性的模块 id(webpack 5 生产模式默认)。 ### 【基础】什么是 tree shaking? **参考答案**:删除未使用代码。依赖 ES 模块的静态导入导出,构建时标记未使用的导出,压缩阶段删除;`sideEffects` 声明哪些模块有副作用。 **追问**:什么情况会失效?→ 使用 CommonJS、模块有副作用但未声明、babel 把 ESM 转成了 CommonJS、动态访问导出对象。 ## 进阶 ### 【进阶】讲讲 webpack 的构建流程。 **参考答案**:合并配置 → 创建 Compiler 并注册插件 → 从入口开始构建模块:调用 loader 转换、解析 AST 收集依赖、递归 → 形成模块依赖图 → 按入口、动态导入和 splitChunks 规则生成 chunk → 生成代码、写入文件。全程通过 tapable 钩子通知插件。 **追问**:Compiler 和 Compilation 的区别?→ Compiler 代表整个 webpack 实例,生命周期贯穿始终;Compilation 代表一次构建(监听模式下每次重新构建创建新的 Compilation)。 ### 【进阶】如何提升 webpack 的构建速度? **参考答案**:持久化缓存;缩小 loader 范围;更快的转译器(swc / esbuild 类 loader);减少或简化 source map;类型检查并行;合理的 `resolve` 配置;必要时考虑 Rspack。 **追问**:怎么确定瓶颈?→ 先用速度分析工具或 `--profile` 统计各阶段和 loader 耗时,再有针对性地优化。 ### 【进阶】什么是模块联邦?适用场景? **参考答案**:webpack 5 提供的能力,让独立构建和部署的应用在运行时互相加载模块,并共享依赖(如同一份 Vue)。用于微前端、多团队独立发布。 **追问**:有什么风险?→ 共享依赖版本不一致、运行时加载失败要降级、类型共享麻烦、调试复杂。 ## 场景题 ### 【场景题】CI 构建十几分钟、首页 JS 几 MB,你怎么优化并防止反弹? **参考答案**:先度量(速度分析、产物分析)→ 构建提速(缓存、swc、并行类型检查)→ 体积优化(懒加载、按需引入、拆包、tree shaking)→ CI 体积预算。详见[构建优化场景](scenarios/build-speed.md)。 **追问**:优化效果怎么证明?→ 对比优化前后的构建时间和关键页面的产物大小、LCP 等指标,用数据说话。 ### 【场景题】要求你写一个 loader,把团队内部的 `.md` 文档直接作为字符串导入组件,怎么做? **参考答案**:loader 导出一个函数,参数是文件内容,用 `this.getOptions()` 读取配置,返回 `export default ` 形式的 JS 代码;在 `module.rules` 中用 `test: /\.md$/` 配置。见 [examples/webpack-config](examples/webpack-config/)。 **追问**:如果要转成 HTML 并支持异步处理?→ 使用 `this.async()` 获取回调,调用 Markdown 解析库后回调结果;注意输出内容的 XSS 风险。