一、 核心概念与原理
-
Webpack 是什么?它解决了什么问题?
- 考察点:定义(静态模块打包器 Static Module Bundler)。解决的问题(模块化开发支持、代码/资源整合与打包、编译/转换代码、代码分割、性能优化等)。
-
Webpack 的核心概念有哪些?请简要解释。
-
考察点:
- 入口 (Entry): 打包的起点文件。
- 输出 (Output): 打包后文件的存放位置和命名规则。
- 加载器 (Loader): 让 Webpack 能够处理非 JavaScript 文件(如 CSS, 图片, TS),或者对 JS 文件进行转换(如 ES6 转 ES5)。Loader 本质上是函数,处理源文件内容。
- 插件 (Plugin): 用于执行更广泛的任务,覆盖从打包优化、资源管理到环境变量注入等。Plugin 可以监听 Webpack 构建生命周期的事件并在特定时刻执行操作。
- 模式 (Mode): development, production, none。控制 Webpack 的内置优化策略。
- (可选) 模块 (Module): Webpack 能处理的任何文件或资源。
- (可选) 代码块 (Chunk): Webpack 打包过程中生成的代码块,最终会输出为文件。
-
-
描述一下 Webpack 的构建流程(大致过程)?
- 考察点:初始化参数 -> 开始编译 -> 确定入口 -> 编译模块(递归依赖分析,调用 Loader 处理模块) -> 完成模块编译 -> 输出资源(根据配置将 Chunk 组合成文件) -> 输出完成。理解其核心是依赖图的构建和资源的输出。
-
Loader 和 Plugin 的区别是什么?
-
考察点:
- 作用对象: Loader 作用于单个模块文件,Plugin 作用于整个构建过程。
- 功能: Loader 用于转换模块内容,Plugin 用于执行更广泛的构建任务(优化、注入、资源管理等)。
- 执行时机: Loader 在模块编译阶段执行,Plugin 在 Webpack 构建生命周期的不同钩子(Hooks)上执行。
- 配置方式: Loader 配置在 module.rules 中,Plugin 配置在 plugins 数组中。
-
二、 配置与使用
-
webpack.config.js 文件的基本结构是怎样的?包含哪些主要配置项?
- 考察点:entry, output, module, plugins, mode, devServer, resolve, optimization 等。
-
如何配置 Loader 来处理 CSS 文件?如何处理图片等静态资源?
- 考察点:module.rules 数组。使用 css-loader(处理 @import, url())、style-loader(将 CSS 注入 标签)或 mini-css-extract-plugin(提取 CSS 到单独文件)。使用 file-loader/url-loader(Webpack 4)或 asset modules(Webpack 5+)处理图片、字体等。
-
如何配置 Babel 来转换 ES6+ 代码?
- 考察点:使用 babel-loader。需要配合 @babel/core, @babel/preset-env 等 Babel 相关包。.babelrc 或 babel.config.js 配置 Babel 预设(preset)和插件(plugin)。
-
output 配置中的 filename 和 chunkFilename 有什么区别?常用的占位符有哪些?
- 考察点:filename 用于入口(entry)产生的 chunk,chunkFilename 用于非入口(如动态导入 import())产生的 chunk。常用占位符:[name] (chunk name), [id] (chunk id), [contenthash] (文件内容 hash,用于缓存控制)。
-
resolve 配置项的作用是什么?常用的配置有哪些?
- 考察点:配置模块解析规则。extensions(自动解析文件扩展名)、alias(创建模块别名)、modules(查找模块的目录)。
-
devServer 配置项的作用是什么?常用的配置有哪些?
- 考察点:提供开发服务器,支持热更新等。port(端口)、hot(开启 HMR)、proxy(配置 API 代理)、static(提供静态文件服务,Webpack 5+)、historyApiFallback(处理 SPA 路由)。
-
什么是模块热替换(Hot Module Replacement, HMR)?如何配置和启用它?
- 考察点:在应用运行时,无需完全刷新页面即可替换、添加或删除模块。提升开发体验。配置:devServer.hot: true,可能需要配合特定框架的 Loader/Plugin(如 react-refresh/babel, vue-loader)以及在入口文件或模块中调用 module.hot.accept() API。
三、 性能优化
-
你了解哪些 Webpack 性能优化策略?
-
考察点:这是一个开放性问题,可以从多个角度回答:
-
构建速度优化:
- 升级 Webpack, Node.js, Loader/Plugin 到最新版本。
- 合理配置 resolve(extensions, alias, modules)。
- 配置 module.noParse 忽略大型库的解析。
- 使用 thread-loader 或 HappyPack(旧)开启多进程构建。
- 使用缓存(cache 配置项,babel-loader 的 cacheDirectory,hard-source-webpack-plugin(旧),terser-webpack-plugin 的缓存)。
- 缩小构建范围(include/exclude 配置 Loader)。
-
输出体积优化:
- 代码分割(Code Splitting):entry 多入口、optimization.splitChunks、动态导入 import()。
- 压缩代码:terser-webpack-plugin(JS 压缩)、css-minimizer-webpack-plugin(CSS 压缩)。
- Tree Shaking(摇树优化):移除未使用的代码(需要 ES6 模块语法支持,mode: 'production' 默认开启)。
- 图片压缩。
- 按需加载/懒加载。
-
用户体验优化:
- 利用浏览器缓存([contenthash])。
- 提取公共代码(splitChunks)。
- 预加载/预获取(Preloading/Prefetching)。
-
-
-
什么是 Tree Shaking?它的工作原理是什么?需要满足哪些条件?
- 考察点:移除 JavaScript 上下文中未引用的代码(dead-code)。原理基于 ES6 模块的静态结构(导入导出关系在编译时确定)。条件:使用 ES6 模块语法 (import/export),Webpack 配置 mode: 'production'(或手动配置优化),确保 Babel 等转换器不将 ES6 模块转为 CommonJS,可能需要在 package.json 中设置 "sideEffects": false 或具体文件列表来帮助 Webpack 判断副作用。
-
什么是代码分割(Code Splitting)?Webpack 中实现代码分割有哪些方式?
-
考察点:将代码拆分成多个 bundle(chunk),可以按需加载或并行加载,提高首屏加载速度。方式:
- 多入口配置 (Entry Points): 简单直接,适用于多页应用。
- optimization.splitChunks 配置: 自动提取公共模块和第三方库。
- 动态导入 (import()) : 按需加载模块,返回 Promise。最常用、最灵活的方式。
-
-
hash, [chunkhash], [contenthash] 的区别是什么?为什么推荐使用 [contenthash]?
-
考察点:都是用于生成带哈希值的文件名,以利用浏览器缓存。
- [chunkhash]: 根据 chunk 内容计算哈希。同一个 chunk 内文件改动,该 chunk 哈希改变。JS 和 CSS 同属一个 chunk 时,改 JS 会导致 CSS 文件名也变。
- [contenthash]: 根据文件内容本身计算哈希。只有文件内容改变,哈希才会改变。是最推荐的方式,可以实现最佳的缓存效果(JS 改动不影响 CSS 文件名)。
-
四、 Loader 和 Plugin 开发(进阶)
-
如果要编写一个自定义 Loader,大致的思路是怎样的?Loader 函数接收什么参数,返回什么?
- 考察点:Loader 是一个导出函数的 Node.js 模块。函数接收源文件内容(content)作为参数,可以进行转换处理,最后 return 处理后的内容(字符串或 Buffer),或者调用 this.callback 返回多个结果(如 content 和 sourcemap)。可以使用 this 上下文对象访问 Webpack 提供的 API。
-
如果要编写一个自定义 Plugin,大致的思路是怎样的?Plugin 的核心是什么?
- 考察点:Plugin 是一个具有 apply 方法的 JavaScript 类(或构造函数)。apply 方法接收 compiler 对象作为参数。在 apply 方法内部,通过 compiler.hooks..tap('PluginName', callback) 来监听 Webpack 构建生命周期的钩子,并在合适的时机执行自定义逻辑。
准备建议:
- 理解核心概念: 牢固掌握 Entry, Output, Loader, Plugin, Mode 的作用和关系。
- 动手配置: 尝试从零开始搭建一个简单的 Webpack 项目,或者修改现有项目的配置,加深理解。
- 关注优化: 性能优化是 Webpack 面试的重点,务必熟悉常见的优化策略和原理。
- 区分 Loader/Plugin: 清晰地知道什么时候用 Loader,什么时候用 Plugin。
- 了解 Webpack 5+ 新特性: Asset Modules, Module Federation, 持久化缓存等。
- 结合项目经验: 思考你在项目中是如何使用 Webpack 的,遇到了哪些问题,是如何解决的。