【webpack】弄清楚webpack 与vite的区别

Webpack 与vite最大的不同,是在开发的时候,webpack 进行了模块转化。 Webpack的功能非常强大,比如模块打包、代码分割、按需加载、HMR、文件建ring、Tree-shaking、Sourcemap、MF、Dev Server、DLL、持久化缓存、Loader缓存等等

而Vite开发模式 unbundle, 因为浏览器原生支持esm,所以根本没做什么 bundle 操作,而是交给了浏览器。在生产的时候用才Rollup构建

原生ESM

先看看原生ESM支持的写法,比如,这种 js-examples,但是我实际运行的时候会碰到一个跨域问题

sql 复制代码
Access to script at 'file:///Users/nanlan/Documents/my-project/js-examples/module-examples/basic-modules/main.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.

报错原因是es6会受到同源策源的限制,所以需要通过HTTP或HTTPS协议从服务器加载你的脚本

js 复制代码
const express = require('express'); const app = express(); 
app.use(express.static('public')); // 'public'是你的静态文件(如HTML,JS,CSS等)所在的目录 
app.listen(3000, () => console.log('Server is running on port 3000'));

然后运行localhost:3000就可以了

Webpack

在Webpack中,构建过程大概分为这么几个阶段初始化Init构建Make生成Seal

  • 初始化阶段: 修整配置参数,创建 Compiler、Compilation 等基础对象,并初始化插件及若干内置工厂、工具类,并最终根据 entry 配置,找到所有入口模块
  • 构建阶段: 从entry找到入口,调用loader转化为JS代码,调用Acorn 转化为AST结构,遍历 AST 找出模块依赖的模块;之后递归遍历所有依赖块,构建出 模块依赖关系图 (dependency graph)
  • 生成阶段: 根据output的配置,将模块拆解成不同的chunk对象,经过一系列优化,再将代码翻译成产物

描述得比较简单, 实际完成这些过程是比较复杂的

Vite

我们来看看 Vite,像模块依赖、文件转换,这些事情都不是在开发的时候做的,而是交给了浏览器去处理,用户启动 dev server 他会通过会通过 middlewares 对请求做拦截,然后对源文件做 resolveloadtransformparse 操作,然后再将转换以后的内容发送给浏览器

unbundle核心

  • 模块之间的依赖关系的解析由浏览器实现;
  • 文件的转换由 dev servermiddlewares 实现并做缓存;
  • 不对源文件做合并捆绑操作;

Vite的缓存

代码总共分为两部分,一部分是第三方依赖,会用 esbuild 进行依赖预构建,然后在浏览器进行强制缓存, Cache-Control: max-age=31536000,immutable,一旦命中,将不会发起请求 而另外一部分是源码, 会根据304 Not Modified 进行协商缓存

  • 强缓存

  • 协商缓存

不得不回顾下浏览器的缓存

浏览器缓存

强缓存

Cache-Control(Http1.1)、Expires(HTTP1.0),这两个可能会同时出现。同时出现的话,则 Cache-Control 会覆盖 Expires,这是因为 Expires 它是一个具体的时间,很可能就因客户端与服务端时间的不同,导致缓存失效。而 Cache-Control 是一个相对时间, 告诉服务器可以缓存多久,而且也具有比较多参数,详见 Cache-Control

  • max-age: 设置多少秒后资源重新生成
  • no-store: 完全禁止缓存
  • no-cache: 在使用缓存前向服务器确认资源是否需要更新
  • 其余参数参考 Cache-Control

Vite 中设置 Cache-Control: max-age=31536000,immutable,这个设置资源可以在本地缓存并在接下来的31536000秒(大约一年)内使用,而无需向服务器发送请求来检查资源是否有更新。immutable:这个指令告诉浏览器,如果资源在max-age指定的时间内,那么即使用户进行了页面刷新,也不需要向服务器发送请求来验证资源是否有更新

源码位置

协商缓存

  • Last-ModifiedIf-Modified-Since是一组HTTP头,服务器通过Last-Modified告诉浏览器资源的最后修改时间,浏览器下次请求时通过If-Modified-Since带上这个时间,服务器会判断资源是否有变化。

  • EtagIf-None-Match是另一组,Etag是资源的唯一标识,浏览器通过If-None-Match发送Etag值,服务器根据这个值判断资源是否变化

Etag/If-None-Match相比Last-Modified/If-Modified-Since更为精确,同时优先级也更高写

总结

Webpack 5 后有 MF, 也有持久化缓存,但是因为在开发的时候有 bundle的存在,Vite是完全得因浏览器完全支持ESM,所以就是在开发的时候不需要unbundle, 那么模块依赖、文件解析都交给了浏览器去处理,所以自然子第一次启动的话,会有白屏时间,之后因为浏览器缓存的缘故,所以在热更新上还是会有优势。但是Webpack有持久化缓存、模块联邦等这些,在大型项目上,与 Vite的体感是相差比较明显的,尤其是在冷启动下,但是小项目中, Webpack 用了模块联邦感觉也不是很明显

参考

漫谈构建工具(四): 为什么有人说 vite 快,有人却说 vite 慢

Modules

相关推荐
小兵张健2 小时前
价值1000的 AI 工作流:Codex 通用前端协作模式
前端·aigc·ai编程
sunny_2 小时前
面试踩大坑!同一段 Node.js 代码,CJS 和 ESM 的执行顺序居然是反的?!99% 的人都答错了
前端·面试·node.js
拉不动的猪2 小时前
移动端调试工具VConsole初始化时的加载阻塞问题
前端·javascript·微信小程序
ayqy贾杰4 小时前
Agent First Engineering
前端·vue.js·面试
IT_陈寒4 小时前
SpringBoot实战:5个让你的API性能翻倍的隐藏技巧
前端·人工智能·后端
iceiceiceice5 小时前
iOS PDF阅读器段评实现:如何从 PDFSelection 精准还原一个自然段
前端·人工智能·ios
大金乄5 小时前
封装一个vue2的elementUI 表格组件(包含表格编辑以及多级表头)
前端·javascript
葡萄城技术团队6 小时前
【性能优化篇】面对万行数据也不卡顿?揭秘协同服务器的“片段机制 (Fragments)”
前端
程序员阿峰6 小时前
2026前端必备:TensorFlow.js,浏览器里的AI引擎,不写Python也能玩转智能
前端
Jans6 小时前
Shipfe — Rust 写的前端静态部署工具:一条命令上线 + 零停机 + 可回滚 + 自动清理
前端