工程化(八股)
esm和cjs的区别
npm,yarn,pnpm的区别
webpack和vite的区别,vite为什么比webpack快
Webpack 和 Vite 都是现代前端构建工具,核心功能是将源代码(JS、CSS、图片等)处理为可在浏览器运行的产物,但两者的设计理念和实现方式有本质区别,这也导致了 Vite 在开发环境下的速度显著优于 Webpack。
区别
| 维度 | Webpack | Vite | 
|---|---|---|
| 开发模式 | 基于 “打包”(Bundle-based) | 基于 “原生 ESM”(ESM-based) | 
| 核心思路 | 提前打包所有模块为 bundle 文件 | 开发时不打包,直接让浏览器解析 ESM | 
| 启动方式 | 先打包再启动开发服务器 | 直接启动服务器,按需编译模块 | 
| 热更新机制 | 重新打包变化模块及其依赖 | 精确更新单个模块,无需重新打包 | 
vite比webpack快原因
1.开发启动阶段:避免“全量预打包”
webpack
开发启动时,Webpack需要递归解析所有依赖,将所有模块打包成一个/多个bundle.js文件后,才会启动开发服务器。项目越大,打包时间越长,启动速度慢
vite
利用现代浏览器原生支持ESM的特性,开发时不做任何打包
启动服务器后,直接向浏览器返回原生 ESM 格式的源代码;
浏览器浏览器解析到import语句时,会主动向服务器请求对应的模块;
服务器仅在收到请求时,才对该模块进行编译(如js转ts sass转css),并返回给浏览器
这种“按需编译”的模式让 Vite 启动时间与项目规模无关(即使项目有 1 万个模块,启动时间也只需几百毫秒)。
2.热更新(HMR)阶段
webpack
当某一模块改变后,webpack需要重新打包该文件及其所有依赖,并将新的bundle发送到浏览器,模块依赖链越长,热更新耗时越久(可能需要几秒)
vite
vite的热更新基于原生ESM模块图,修改模块后仅重新编译被修改的模块(无需处理依赖链),通过import.meta.hotAPI通知浏览器替换该模块,不影响其他模块。即使是大型项目,热更新也能在毫秒级完成
3.依赖处理:预构建与缓存
Vite 并非完全不处理依赖,而是通过 “预构建” 优化第三方库(如 React、Vue)的加载:
第三方库通常是 CommonJS 格式(非 ESM),且包含大量小模块(如 Lodash 有数百个文件),浏览器直接加载会触发大量请求。
首次启动时,vite会用esbuild(Go 语言编写,比js快10-100倍)将第三方依赖预构建为ESM格式单文件(减少请求数),预构建结果会缓存到node_modules/.vite,后续启动直接复用,无需重新处理。
4.编译工具:esbuild 替代 Babel/Terser
Vite 在开发环境中使用 esbuild 处理代码转换(如 TS→JS、JSX→JS、压缩),而 Webpack 通常使用 Babel、Terser 等 JS 编写的工具:
- esbuild 基于 Go 语言,性能远超 JS 工具(如编译 TS 的速度是 tsc 的 20 倍以上); 
- 仅在生产环境,Vite 才使用 Rollup 打包(因 esbuild 对代码分割、CSS 处理等生产特性支持不足)。 
webpack的loader和plugin
1.Loader
Webpack 本质上只能处理 JavaScript 和 JSON 文件,而 loader 的作用是将非 JS 模块(如 CSS、图片、TS、Vue 组件等)转换为 Webpack 可识别的模块,以便纳入打包流程。
2.Plugin
Plugin(插件)是 用于扩展 Webpack 整体功能的工具,可以介入 Webpack 打包的整个生命周期(如打包前清理输出目录、打包后压缩文件、生成 HTML 等),解决 loader 无法处理的复杂问题。
webpack打包的全流程
Webpack 的打包流程是一个从 “读取配置” 到 “输出产物” 的完整生命周期,核心是将多个模块(JS、CSS、图片等)按依赖关系合并为最终可运行的静态资源。
(一)初始化阶段
1.读取配置文件
Webpack启动时,首先读取项目根目录的webpack.config.js,解析其中的配置项(如 entry 入口、output 输出路径、loader、plugin 等)。若未指定配置文件,使用默认配置(入口为 ./src/index.js,输出为 ./dist/main.js)。
2.初始化Compiler实例
根据配置创建 Compiler 对象(Webpack 的核心编译器),它包含了整个打包流程的所有信息,并注册配置中所有的 plugin(插件)。
3.确认入口文件
从配置的 entry 字段确定入口模块(可配置多入口,如 { app: './src/app.js', admin: './src/admin.js' }),作为依赖解析的起点。
