工程化
Webpack
Webpack 是什么?它的核心功能是什么?
- Webpack 是模块化打包工具,将分散的 JS、CSS、图片等资源视为模块,分析依赖关系并打包成静态文件。
- 核心功能:代码编译、依赖分析、代码分割、资源优化。
Webpack 的核心概念是什么?
- 入口(Entry):指示 Webpack 应该从哪个文件开始构建依赖图(可以指定一个或多个入口文件)。
- 输出(Output):输出指示 Webpack 在哪里输出打包文件。
- 加载器(Loader):允许 Webpack 处理非 JavaScript 文件(如 CSS、图片、字体等)。
- 插件(Plugin):用于扩展 Webpack 功能(如:优化资源、压缩代码、添加环境变量等)。
- 模式(Mode):用于指定 Webpack 的构建模式,可以是开发模式(development)、生产模式(production)或其他。
Loader 和 Plugin 的作用及区别是什么?
- Loader:处理非 JS 文件(如转换 SASS/LESS 为 CSS、转换 ES6/ES7 为 ES5 等),按顺序链式调用。
- Plugin:扩展 Webpack 功能(如生成 HTML 文件,代码压缩、资源优化、环境变量注入等),通过钩子影响打包全流程。
记忆点:Loader 处理非 JS 文件,Plugin 扩展 Webpack 功能。
Webpack 如何实现代码分割(Code Splitting)?
- 入口分割:配置多入口(
entry: { a: 'a.js', b: 'b.js' }
)。 - 动态导入:使用
import()
语法,生成独立 chunk。 - 配置
optimization.splitChunks
提取公共代码。
记忆点:多入口 + 动态导入 + splitChunks 优化。
- 入口分割:配置多入口(
Webpack 的 Tree Shaking 如何生效?需要满足哪些条件?
- 基于 ES Module 静态语法(
import/export
),删除未使用代码。 - 条件:生产模式(
mode: 'production'
)、禁用 Babel 的 ESM 转换、package.json
中标记sideEffects: false
。
记忆点:ESM 语法 + 生产模式 + sideEffects 标记。
- 基于 ES Module 静态语法(
Webpack 构建性能优化有哪些常见手段?
- Tree Shaking: 使用 ES6 模块语法并启用 Tree Shaking 来消除未使用的代码,减小打包体积。
- 代码拆分 (Code Splitting): 将应用程序拆分为多个 bundle,并实现按需加载,以减少初始加载时需要下载的资源量,加快页面加载速度。
- 使用 CDN: 将第三方依赖库(如 React、Vue、jQuery 等)从打包中移除,并通过 CDN 引入,减小打包体积并加速页面加载。
- 压缩资源: 使用 Webpack 的压缩插件(如 uglifyjs-webpack-plugin、terser-webpack-plugin 等)来压缩 JavaScript 代码、CSS 代码等,减小文件体积。
- 优化图片: 使用 image-webpack-loader 或者 url-loader 来优化图片资源,压缩图片并将小图片转换为 base64 格式,减少 HTTP 请求并加快加载速度。
- 提取公共代码: 使用 Webpack 的 SplitChunksPlugin 来提取公共模块,减少重复代码,并将其打包到单独的文件中,以便浏览器缓存和复用。
- 缓存优化: 使用 Webpack 的持久化缓存(persistent caching)功能,利用构建结果的 hash 值来标识构建结果的变化,从而提高构建效率。
- 多进程构建: 使用 webpack-parallel-uglify-plugin、thread-loader 等插件来启用多进程构建,利用多核 CPU 提高构建速度。
- 减少不必要的 Loader: 只加载必要的 Loader,避免加载过多的 Loader,以减少构建时间。
- 使用 DllPlugin: 使用 webpack.DllPlugin 来预先编译第三方库,以减少每次构建时的依赖分析时间。
- 减少文件搜索范围: 使用 resolve.modules、resolve.extensions、resolve.alias 等配置来减少文件搜索范围,提高构建速度。
Vite
Vite 是什么?它解决了什么问题?
- Vite 是新一代前端构建工具,解决传统打包工具(如 Webpack)开发环境冷启动慢、热更新效率低的问题。
- 核心思想:开发环境基于浏览器原生 ESM,生产环境用 Rollup 打包。
Vite 为什么开发环境比 Webpack 快?
- 无打包:浏览器直接加载 ESM 模块。
- 按需编译:只编译在浏览器中实际使用的代码。
- 预构建:用 esbuild 将 CommonJS 依赖转换为 ESM。
- 并行构建:多个进程中同时编译代码。
- 缓存:依赖预构建结果缓存,避免重复编译。
记忆点:原生 ESM + esbuild 预构建 + 缓存机制。
Vite 的热更新(HMR)为什么高效?
- 基于浏览器原生 ESM,仅更新修改的模块,无需重建依赖图。
- 服务端通过
WebSocket
推送更新信息,客户端精准替换模块。
记忆点:精准模块替换 + WebSocket 推送。
Vite 如何处理 TypeScript 和 CSS 预处理器?
- TypeScript:内置支持,直接编译(无需额外配置)。
- CSS 预处理器:安装对应工具(如 sass/less/stylus)即可直接使用。
记忆点:TS 开箱即用,CSS 预处理需安装工具。
Vite 生产环境打包为什么选择 Rollup?
- Rollup 的 Tree Shaking 更彻底,输出代码更小。
- 更适合生成符合 ESM 标准的库或应用。
记忆点:Rollup 更小的输出 + 更严格的 ESM 支持。
Rollup
Rollup 是什么?它的设计目标是什么?
- Rollup 是专注于 JavaScript 库打包的工具,设计目标是生成更小、更高效的代码,尤其适合库的发布。
核心优势:Tree Shaking 彻底、输出格式灵活(ESM/UMD 等)。
- Rollup 是专注于 JavaScript 库打包的工具,设计目标是生成更小、更高效的代码,尤其适合库的发布。
Rollup 和 Webpack 的主要区别是什么?
- Rollup:适合库,输出扁平化代码,Tree Shaking 更彻底。
- Webpack:适合应用,支持代码分割、动态加载等复杂功能。
Rollup 如何处理 CommonJS 模块?
- 需安装
@rollup/plugin-commonjs
插件转换 CommonJS 为 ESM。 - 配合
@rollup/plugin-node-resolve
解析node_modules
依赖。
记忆点:CommonJS 需插件转换,Node 模块需解析插件。
- 需安装
为什么 Rollup 的 Tree Shaking 更高效?
- 基于 ESM 静态分析,删除所有未使用的代码。
- 输出结果无 Webpack 的模块包装代码,结构更扁平。
记忆点:ESM 静态分析 + 无冗余代码。
Rollup 如何实现代码分割(Code Splitting)?
- 配置
output.dir
代替output.file
,输出多文件。 - 使用动态导入(
import()
)自动分割代码。
记忆点:多文件输出 + 动态导入自动分割。
- 配置
Gulp
Gulp 是什么?它适用于什么场景?
- Gulp 是基于流的自动化任务运行器,适用于文件转换、压缩、打包等重复性任务。
- 典型场景:静态资源处理(如压缩图片、编译 SASS)。
Gulp 的流(Stream)处理机制是什么?
- 通过
gulp.src()
读取文件生成 Vinyl 虚拟文件流。 - 使用
pipe()
连接插件处理文件(如gulp-sass
编译 CSS)。 - 最终通过
gulp.dest()
输出到磁盘。
记忆点:src → pipe 处理链 → dest 输出。
- 通过
如何用 Gulp 监听文件变化并自动执行任务?
- 使用
gulp.watch()
监听文件变化。 - 示例:
gulp.watch('src/*.scss', gulp.series('compile-sass'))
。
- 使用
Gulp 如何处理任务间的依赖关系?
- 使用
gulp.series()
顺序执行任务(如先清理再构建)。 - 使用
gulp.parallel()
并行执行任务(如同时压缩 JS 和 CSS)。
记忆点:series 串行,parallel 并行。
- 使用
Tree Shaking
Tree Shaking 是什么?它的设计目标是什么?
- Tree Shaking 是消除 JavaScript 中未使用代码的优化技术,通过静态分析模块依赖关系,删除未被引用的代码(“死代码”)。
- 目标:减少代码体积,提升执行效率。
记忆点:静态分析依赖,删除无用代码。
Tree Shaking 的实现原理是什么?
- 依赖 ES Module:利用
import/export
的静态语法特性(编译时分析依赖)。 - 标记未引用代码:构建工具(如 Webpack/Rollup)标记未被使用的导出。
- 删除阶段:在压缩阶段(如 Terser)移除标记的代码。
记忆点:ESM 静态分析 → 标记 → 压缩删除。
- 依赖 ES Module:利用
如何确保 Tree Shaking 生效?需要满足哪些条件?
- 代码层面:使用 ES Module(
import/export
),避免 CommonJS。 - 工具配置:
- Webpack:
mode: 'production'
,optimization.usedExports: true
。 - Rollup:默认开启,无需额外配置。
- Webpack:
- 库标记:在
package.json
中设置sideEffects: false
(或指定副作用文件)。
记忆点:ESM 语法 + 生产模式 + sideEffects 标记。
- 代码层面:使用 ES Module(