Files
zhuangang/topics/frontend/webpack/interview.md
T

4.1 KiB
Raw Blame History

id, title, type, domain, stack, tags, level, related, week
id title type domain stack tags level related week
frontend.webpack.interview webpack 面试题 interview frontend
webpack
webpack
loader
plugin
tree shaking
面试
intermediate
frontend.webpack.build-optimization
frontend.vite.interview
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 体积预算。详见构建优化场景。

追问:优化效果怎么证明?→ 对比优化前后的构建时间和关键页面的产物大小、LCP 等指标,用数据说话。

【场景题】要求你写一个 loader,把团队内部的 .md 文档直接作为字符串导入组件,怎么做?

参考答案:loader 导出一个函数,参数是文件内容,用 this.getOptions() 读取配置,返回 export default <JSON 字符串> 形式的 JS 代码;在 module.rules 中用 test: /\.md$/ 配置。见 examples/webpack-config。

追问:如果要转成 HTML 并支持异步处理?→ 使用 this.async() 获取回调,调用 Markdown 解析库后回调结果;注意输出内容的 XSS 风险。