【蜻蜓点水】了解一下 vite 下一代前端开发与构建工具

简介: 【蜻蜓点水】了解一下 vite 下一代前端开发与构建工具

Vite 是什么

9bc765b6712344cdb8a3b6bd9a9e5728.png




Vite(法语单词,“快” 的意思)由 vue 作者尤雨溪开发的 web 开发工具,是一种新型的前端构建工具。


Vite,一个基于浏览器原生 ES imports 的开发服务器,利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随启随用,它是下一代前端开发与构建工具。



Vite 优缺点


优点:


💡 极速的服务启动:使用原生 ESM 文件,无需打包

⚡️ 轻量快速的热重载:无论应用程序大小如何,都始终极快的模块热重载(HMR)

🛠️ 丰富的功能:对 TypeScript、JSX、CSS 等支持开箱即用

📦 优化的构建:可选 “多页应用” 或 “库” 模式的预配置 Rollup 构建

🔩 通用的插件:在开发和构建之间共享 Rollup-superset 插件接口

🔑 完全类型化的API:灵活的 API 和完整的 TypeScript 类型




缺点:

  1. 生态不如 webpack 丰富
  2. 生产环境的构建,目前用的 Rollup:原因在于 ESBuild 对于代码分割和 CSS 处理方面不是很友好



为什么选 Vite




当代的前端构建工具有很多,比较受欢迎的有 Webpack、Rollup、Parcel等,绝大多数脚手架工具都是使用 Webpack 作为构建工具,如 Vue-CLI。


在利用 Webpack 作为构建工具时,开发过程中,每次修改代码,都会导致重新编译,当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。这就会导致热更新的速度也随之变慢,甚至要几秒钟才能看到视图的更新。生产环境下,它将各个模块之间通过编码的方式联系在一起,最终生成一个庞大的 bundle 文件。


导致这些问题出现的原因,有以下几点:


   HTTP 1.1 时代,各个浏览器资源请求并发是有上限的


       如谷歌浏览器为 6 个,这导致你必须要减少资源请求数


   浏览器并不支持 CommonJS 模块化系统


       它不能直接运行在浏览器环境下,它是 Node 提出的模块化规范,所以需要经过 Webpack 的打包,编译成浏览器可识别的 JS 脚本)


   模块与模块之间的依赖顺序和管理问题


       文件依赖层级越多,静态资源也就变得越多,如果一个资源有 100 个依赖关系,可能需要加载 100 个网络请求,这对生产环境可能是灾难,所以在生产环境最终会打包成一个 bundle 脚本,会提前进行资源按需加载的配置。



不打包的构建趋势原因


   工程越来越庞大,热更新变得缓慢,影响开发体验。


   各大浏览器已经开始慢慢的支持原生 ES Module (谷歌、火狐、Safari、Edge 的最新版本,都已支持。)


   HTTP 2.0 采用的多路复用。不用太担心请求并发量的问题。


   越来越多的 npm 包开始采用了原生 ESM 的开发形式。


bundle 和 bundleless 的区别

Bundle(Webpack) Bundleless(Vite)
开发环境启动 需完成打包构建,存入内存之后才能启动 只需启动开发服务器,按需加载
项目构建时间 随项目体积线性增长 构建时间复杂度O(1)
文件加载 加载打包后的 bundle 通过请求,映射到本地
文件更新 重新打包构建 不重新打包
开发调试 依赖 Source Map 可单文件直接调试
周边生态 loader和plugin非常丰富 生态不够webpack成熟


拓展:[Vue官方成员:Vite生态发展的怎么样了



聊一聊 ES Module


历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 Ruby 的 require、Python 的 import,甚至就连 CSS 都有 @import,但是 JavaScript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。


在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。


ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。


// CommonJS模块
let { stat, exists, readfile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;


上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。


ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,再通过 import 命令输入。

// ES6模块
import { stat, exists, readFile } from 'fs';



上面代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。


模块功能主要由两个命令构成:export 和 import。


   export 命令用于规定模块的对外接口

   import 命令用于输入其他模块提供的功能



ES Module 基本特性


   ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict"


   ES6 模块之中,顶层的 this 指向 undefined,即不应该在顶层代码使用 this


   一个模块就是一个独立的文件,该文件内部的所有变量,外部无法获取。


   ESM 是通过 CORS 的方式请求外部 JS 模块的


   ESM 的 script 标签会延迟执行脚本(浏览器页面渲染后执行)



Vite 进行了什么改进


1、缓慢的服务器启动


当冷启动开发服务器时,基于打包器的方式是在提供服务前去急切地抓取和构建你的整个应用。

那么 Vite 是怎么处理的?


   Vite 通过在一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间。


   依赖 大多为在开发时不会变动的纯 JavaScript。一些较大的依赖(例如有上百个模块的组件库)处理的代价也很高。依赖也通常会存在多种模块化格式(例如 ESM 或者 CommonJS)。


   Vite 将会使用 esbuild 预构建依赖。Esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。


   源码 通常包含一些并非直接是 JavaScript 的文件,需要转换(例如 JSX,CSS 或者 Vue/Svelte 组件),时常会被编辑。同时,并不是所有的源码都需要同时被加载(例如基于路由拆分的代码模块)。


   Vite 以 原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。


Vue 脚手架工具 vue-cli 使用 webpack 进行打包,开发时可以启动本地开发服务器,实时预览。因为需要对整个项目文件进行打包,开发服务器启动缓慢。



webpack 打包过程:


   识别入口文件


   通过逐层识别模块依赖。(Commonjs、amd 或者 es6 的 import,webpack 都会对其进行分析。来获取代码的依赖)


   webpack 做的就是分析代码,转换代码,编译代码,输出代码


   最终形成打包后的代码


8fcfc875b1ae426abc9d53f734011c07.png


  1. Vite 只启动一台静态页面的服务器,对文件代码不打包,服务器会根据客户端的请求加载不同的模块处理,实现真正的按需加载。

举个例子:


当声明一个 script 标签类型为 module 时:

<script type="module" src="/src/main.js"></script>


浏览器就会像服务器发起一个GET:http://localhost:3000/src/main.js 去请求 main.js 文件:


// /src/main.js:
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')


浏览器请求到了 main.js 文件,检测到内部含有 import 引入的包,又会对其内部的 import 引用发起 HTTP 请求获取模块的内容文件

GET http://localhost:3000/@modules/vue.js
GET http://localhost:3000/src/App.vue


而 Vite 的主要功能就是通过劫持浏览器的这些请求,并在后端进行相应的处理将项目中使用的文件通过简单的分解与整合,然后再返回给浏览器,vite整个过程中没有对文件进行打包编译。


0f612d6768cf454daa8fe792518afdea.png



2、缓慢的更新

基于打包器启动时,重建整个包的效率很低。原因显而易见:因为这样更新速度会随着应用体积增长而直线下降。


一些打包器的开发服务器将构建内容存入内存,这样它们只需要在文件更改时使模块图的一部分失活,但它也仍需要整个重新构建并重载页面。这样代价很高,并且重新加载页面会消除应用的当前状态,所以打包器支持了动态模块热重载(HMR):允许一个模块 “热替换” 它自己,而不会影响页面其余部分。这大大改进了开发体验 —— 然而,在实践中我们发现,即使采用了 HMR 模式,其热更新速度也会随着应用规模的增长而显著下降。


那么 Vite 是怎么处理的?


   在 Vite 中,HMR 是在原生 ESM 上执行的。当编辑一个文件时,Vite 只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失活(大多数时候只是模块本身),使得无论应用大小如何,HMR 始终能保持快速更新。


   Vite 同时利用 HTTP 头来加速整个页面的重新加载(再次让浏览器为我们做更多事情):源码模块的请求会根据 304 Not Modified 进行协商缓存,而依赖模块请求则会通过 Cache-Control: max-age=31536000,immutable 进行强缓存,因此一旦被缓存它们将不需要再次请求。



Vite 构建原理

Vite 的生产模式和开发模式是不同的概念。Vite 在开发模式下,有一个 依赖预构建 的概念。


什么是依赖预构建

在 Vite 启动开发服务器之后,它将第三方依赖的多个静态资源整合为一个,比如 lodash、qs、axios 等这类资源包,存入 ·node_modules/.vite 文件下。


为什么需要依赖预构建

如果直接采用 ES Module 的形式开发代码,会产生一大串依赖,就好像俄罗斯套娃一样,一层一层的嵌套,在浏览器资源有限的情况下,同时请求大量的静态资源,会造成浏览器的卡顿,并且资源响应的时间也会变慢。


下面通过两个例子来详细分析为什么需要依赖预构建。





目录
相关文章
|
19天前
|
缓存 监控 前端开发
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第26天】前端工程化是现代Web开发的重要趋势,通过将前端代码视为工程来管理,提高了开发效率和质量。本文详细对比了Webpack和Gulp两大主流构建工具的选择与配置优化,并提供了具体示例代码。Webpack擅长模块化打包和资源管理,而Gulp则在任务编写和自动化构建方面更具灵活性。两者各有优势,需根据项目需求进行选择和优化。
48 7
|
18天前
|
缓存 前端开发 JavaScript
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第27天】在现代前端开发中,构建工具的选择对项目的效率和可维护性至关重要。本文比较了Webpack和Gulp两个流行的构建工具,介绍了它们的特点和适用场景,并提供了配置优化的最佳实践。Webpack适合大型模块化项目,Gulp则适用于快速自动化构建流程。通过合理的配置优化,可以显著提升构建效率和性能。
31 2
|
23天前
|
前端开发 JavaScript 开发工具
Vite 4.0 发布,下一代的前端工具链
【10月更文挑战第21天】Vite 4.0 的发布标志着前端开发领域的又一次重要进步。它为开发者带来了更高效、更智能、更具创新性的开发体验,正逐渐成为下一代前端工具链的引领者。
|
1月前
|
前端开发 JavaScript
Vite 多种前端框架的构建
Vite 多种前端框架的构建
|
1月前
|
资源调度 前端开发 JavaScript
Vite:新一代前端构建工具的革命性体验
【10月更文挑战第13天】Vite:新一代前端构建工具的革命性体验
|
1月前
|
前端开发 JavaScript 中间件
Vite:下一代前端构建工具的崛起
【10月更文挑战第13天】Vite:下一代前端构建工具的崛起
|
1月前
|
JSON 前端开发 JavaScript
Vite:新一代前端构建工具的崛起
【10月更文挑战第13天】Vite:新一代前端构建工具的崛起
|
3月前
|
缓存 前端开发 JavaScript
前端项目性能优化:使用vite的分包策略
【8月更文挑战第4天】Vite性能优化-分包策略
116 2
前端项目性能优化:使用vite的分包策略
|
3月前
|
前端开发 Java C++
超简单使用Vite+Vue3构建共享开发和分模块打包的前端项目
使用Vite和Vue3构建支持共享组件和分模块独立打包的前端项目的方法。
440 0
超简单使用Vite+Vue3构建共享开发和分模块打包的前端项目
|
3月前
|
JavaScript 前端开发
什么是前端构建工具?vite和vite脚手架的关系!
【8月更文挑战第1天】前端构建工具简析
84 4