vite 底层剖析

打印 上一主题 下一主题

主题 1788|帖子 1788|积分 5364

vite

目前大多数框架的前端构建工具都已经被vite代替,相信你已经使用过vite了。但是在使用过程中,vite对我来说一直是含糊的,现在就来一探究竟,为啥它更好?
接下来我将为从以下几点出发,究其原理
一、原生ES模块

1、Common JS



  • 文件即模块,每一个文件都是一个 Module 实例,全部代码都运行带模块作用域,不会污染全局作用域(由于CommonJS 输出的是值的拷贝)
  • 全部文件运行时同步加载,模块加载的顺序是按照其在代码中出现的顺序,加载完再执行。
  • 每个模块加载一次后就会被缓存。后续require时,①先查抄缓存中是否存在,②假如缓存中没有,查抄是否是焦点模块,假如是就直接加载,③假如不是焦点模块,查抄是否是文件模块,剖析路径,根据解出的路径定位文件,然后执行,④假如以上都不是,沿当前路径向上级逐级递归,直到根目次的 node_modules 目次
  • CommonJS  模块直接放在欣赏器中是无法执行的,所以要想在欣赏器中运行,须要使用额外的工具(browserify)
2、ES Module



  • 欣赏器支持: ES6 Module 也被成为 ES Module,是由ESMAScript 官方提出的模块化规范。目前已经得到了当代欣赏器的支持。假如在HTML中到场type ="module"属性的 script 标签,那么欣赏器会按照 ES Module 规范来举行以来加载和模块剖析,这也是 vite 在开发阶段实现 no-bundle 的原因。由于欣赏器可以加载模块,所以即使不打包可以顺遂运行模块代码。
  • 动态导入,按需加载
  1. <script type="module">
  2. (async () => {
  3.    const moduleSpecifier = './lib.mjs';
  4.    const {repeat, shout} = await import(moduleSpecifier);
  5.    repeat('hello');
  6.    // → 'hello hello'
  7.    shout('Dynamic import in action');
  8.    // → 'DYNAMIC IMPORT IN ACTION!'
  9. })();
  10. </script>
复制代码


  • import map:支持绝对路径(www.baidi.com)、相对路径(./module),同时支持直接写一个第三方包名,如 react、lodash。前两种都是欣赏器原生支持的,但是对于第三中,放在欣赏器中是无法直接执行的,ESM 办理了这个问题,这里不详细表明,可自行搜索
vite 使用欣赏器对原生ES模块的支持,接纳按需加载的方式,每次请求一个模块,Vite仅仅返回该模块的内容,而不是整个应用的捆绑文件。
但是!webpack是通过捆绑的方式,将全部模块打包成一个或多个文件,这意味着什么,意味着我们在启动项目是须要对整个应用举行打包,会导致长时间的等待
二、预构建

1、预构建办理了什么问题



  • 将其他格式(比方 UMD 、CommonJS)的产物转换为 ESM 格式,使其在欣赏器通过 <script type = "module"><script/> 的方式正常加载。举个例子:大名鼎鼎的 React 就是基于 CommonJS ,而这种格式在vite中是无法直接运行的,但是Vite 没有办法限定第三方的规范,所以改变不了别人,那就改变自己,内部转换
  • 打包第三方库的代码,将各个第三方库分散的文件归并在一起,镌汰 HTTP 请求,制止页面加载性能劣化。举个例子:loadsh-es 是ES 版本,vite可以直接运行,但实际上,在它加载时会发出特别多的请求,导致页面加载的前几秒几乎处于卡顿状态。每次 import 都会触发一个新的文件请求,假如不加控制,会触发成百上千个网络请求,而 Chrome 对同一个域名在只能同时支持 6 个 HTTP 并发请求,导致页面加载十分缓慢。在到场依靠预构建之后,loadsh-es 的代码被打包成一个文件,这样请求的数量会镌汰很多,减轻欣赏器压力,页面加载速率变快。
三、双引擎(EsBuild 和 Rollup)

1、EsBuild 预构建

esbuild 在 Vite 中的作用会合在提拔构建速率、优化依靠处置惩罚和简化开发体验


  • 快速构建
    esbuild 是用 go 编写的构建工具,具有极快的编译速率。使得 Vite 在开发环境中可以快速响应文件变动,提供及时反馈
  • 多核并存
    js 是单线程串行,esbuild 直接新开一个线程 ,多线程并行,充分发挥多核优势
  • 代码压缩,镌汰内存
    esbuild 提供了一个 minify 配置允许用户去压缩代码体积
2、Rollup 打包

vite 选择在生产环境中使用Rollup打包,并基于Rollup 本身成熟的打包能力举行扩展和优化


  • css代码分割。假如某个异步模块中引入了一些 CSS 代码,Vite 就会主动将这些 CSS 抽取出来生成单独的文件,进步线上产物的缓存复用率。
  • 主动预加载。Vite 会主动为入口 chunk 的依靠主动生成预加载标签。这种恰当预加载的做法会让欣赏器提前下载好资源,优化页面性能。
  • 异步Chunks 加载优化。在异步引入的 Chunk 中,通常会有一些公用的模块,如现有两个异步引入的 Chunk: A 和 B,而且两者有一个公共依靠 C一般情况下,Rollup 打包之后,会先请求 A,然后欣赏器在加载 A 的过程中才决定请求和加载 C,但 Vite 举行优化之后,请求 A的同时会主动预加载 C,通过优化 Rollup 产物依靠加载方式节流了不须要的网络开销。
  • 多产物配置。同一个入口文件,打包出多种格式的产物
  1. const buildOptions = {
  2.   input: ["src/index.js"],
  3.   // 将 output 改造成一个数组
  4.   output: [
  5.     {
  6.       dir: "dist/es",
  7.       format: "esm",
  8.     },
  9.     {
  10.       dir: "dist/cjs",
  11.       format: "cjs",
  12.     },
  13.   ],
  14. };
  15. export default buildOptions;
复制代码


  • 多入口配置,将 input 设置为一个数组或者一个对象:
  1. {
  2.   input: ["src/index.js", "src/util.js"]
  3. }
  4. // 或者
  5. {
  6.   input: {
  7.     index: "src/index.js",
  8.     util: "src/util.js",
  9.   },
  10. }
复制代码
四、热模块更新(HMR)

vite 热更新过程

  • 创建一个 websocket 服务端和 client 文件,启动服务
  • 通过 chokidar 监听文件变动
  • 当代码变动后,服务端举行判断并推送到客户端
  • 客户端根据保举的信息执行不同操纵的更新

webpack 热更新过程

  • 使用 webpack-dev-server (后面简称 WDS)托管静态资源,同时以 Runtime 方式注入一段处置惩罚 HMR 逻辑的客户端代码;
  • 欣赏器加载页面后,与 WDS 建立 WebSocket 连接;
    Webpack 监听到文件变化后,增量构建发生变动的模块,
  • 通过 WebSocket 发送 hash 变乱;
  • 欣赏器吸收到 hash 变乱后,请求 manifest 资源文件,确认增量变动范围;
  • 欣赏器加载发生变动的增量模块;
  • Webpack 运行时触发变动模块的 module.hot.accept 回调,执行代码变动逻辑;
  • done。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

傲渊山岳

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表