2021-03-18【技术】关于前端新玩具:Vite 及相关思考

Vite 的定义
Vite 是面向现代浏览器的一个更轻、更快的 Web 应用开发工具,核心基于 ECMAScript 标准原生模块系统(ES Modules)实现。

从表象功能上看,Vite 可以取代基于 Webpack 的 vue-cli 或者 cra 的集成式开发工具,提供全新的一种开发体验。

Vite 的由来
在此之前,如果我们所开发的应用比较复杂(代码量偏大),使用 Webpack 的开发过程相对没有那么「丝滑」,具体表现为以下两点:

Webpack Dev Server 冷启动时间会比较长,稍大一点的项目启动开发服务都需要等待 10 - 20 秒;
Webpack HMR 热更新的反应速度比较慢,修改完代码需要等待编译器全部编译完成才能开始同步到浏览器;
快速上手
这里我们话不多说,先上手体验一下 Vite,然后再来分析其内部的思路和想法。

Vite 官方目前提供了一个比较简单的脚手架:create-vite-app,可以使用这个脚手架快速创建一个使用 Vite 构建的 Vue.js 应用

$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev

如果使用 yarn:

$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev

P.S.
npm init 或者 yarn create 是这两个包管理工具提供的新功能,其内部就是自动去安装一个 create-<xxx> 的模块(临时),然后自动执行这个模块中的 bin。例如:yarn create react-app my-react-app 就相当于先 yarn global add create-react-app,然后自动执行 create-react-app my-react-app。

对比差异点

打开生成的项目过后,你会发现就是一个很普通的 Vue.js 应用,没有太多特殊的地方。
不过相比于之前 vue-cli 创建的项目或者是基于 Webpack 搭建的 Vue.js 项目,这里的开发依赖非常简单,只有 vite 和 @vue/compiler-sfc。

{
  "name": "vite-demo",
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  },
  "dependencies": {
    "vue": "^3.0.0-rc.1"
  },
  "devDependencies": {
    "vite": "^1.0.0-rc.1",
    "@vue/compiler-sfc": "^3.0.0-rc.1"
  }
} 

Vite 就是我们今天要介绍的主角,而 @vue/compiler-sfc 就是用来编译我们项目中 .vue 结尾的单文件组件(SFC),它取代的就是 Vue.js 2.x 时使用的 vue-template-compiler。

再者就是 Vue.js 的版本是 3.0。这里尤其需要注意:Vite 目前只支持 Vue.js 3.0 版本。

在vue中,因为 Webpack Dev Server 在启动时,需要先 build 一遍,而 build 的过程是需要耗费很多时间的。


vue-cli-service serve

而 Vite 则完全不同,当我们执行 vite serve 时,内部直接启动了 Web Server,并不会先编译所有的代码文件。
那仅仅是启动 Web Server,速度上自然就快了很多。


vite serve

原理:
像 Webpack 这类工具的做法是将所有模块提前编译、打包进 bundle 里,换句话说,不管模块是否会被执行,都要被编译和打包到 bundle 里。随着项目越来越大打包后的 bundle 也越来越大,打包的速度自然也就越来越慢。

Vite 利用现代浏览器原生支持 ESM 特性,省略了对模块的打包。对于需要编译的文件,Vite 采用的是另外一种模式:即时编译。也就是说,只有具体去请求某个文件时才会编译这个文件。所以,这种「即时编译」的好处主要体现在:按需编译。

除此之外

Vite 还提供了一个目前在帮助列表中并没有呈现的一个子命令:optimize。

这个命令的作用就是单独的去「优化依赖」。

所谓的「优化依赖」,指的就是自动去把代码中依赖的第三方模块提前编译出来。

例如,我们在代码中通过 import 载入了 vue 这个模块,那通过这个命令就会自动将这个模块打包成一个单独的 ESM bundle, 放到 node_modules/.vite_opt_cache 目录中。

这样后续请求这个文件时就不需要再即时去加载了。

HMR

同样也是模式的问题,热更新的时候,Vite 只需要立即编译当前所修改的文件即可,所以响应速度非常快。

而 Webpack 修改某个文件过后,会自动以这个文件为入口重写 build 一次,所有的涉及到的依赖也都会被加载一遍,所以反应速度会慢很多。

Build

Vite 在生产模式下打包,需要使用 vite build 命令。

这个命令内部采用的是 Rollup 完成的应用打包,最终还是会把文件都提前编译并打包到一起。

对于 Code Splitting 需求,Vite 内部采用的就是原生 Dynamic imports 特性实现的,所以打包结果还是只能够支持现代浏览器。

不过好在 Dynamic imports 特性是可以有 Polyfill 的:也就是说,只要你想,它也可以运行在相对低版本的浏览器中。

打包 or 不打包

随着Vite 的出现,引发了另外一个值得我们思考的问题:究竟还有没有必要打包应用?

毕竟在它之前,我们使用 Webpack 打包应用代码,使之成为一个 bundle.js,主要有两个原因:
1、浏览器环境并不支持模块化
2、零散的模块文件会产生大量的 HTTP 请求
随着浏览器的对 ES 标准支持的逐渐完善,第一个问题已经慢慢不存在了。现阶段绝大多数浏览器都是支持 ES Modules 的。
零散模块文件确实会产生大量的 HTTP 请求,而大量的 HTTP 请求在浏览器端就会并发请求资源的问题;
在并行请求时,排在后面的请求就因为域名链接数已超过限制,而被挂起等待了一段时间。

在 HTTP 1.1 的标准下,每次请求都需要单独建立 TCP 链接,经过完整的通讯过程,非常耗时;

image

而且每次请求除了请求体中的内容,请求头中也会包含很多数据,大量请求的情况下也会浪费很多资源。

但是这些问题随着 HTTP 2 的出现,也就不复存在了。

image.png

在 HTTP/2 中,有了二进制分帧之后,HTTP /2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2 中:

同域名下所有通信都在单个连接上完成。
单个连接可以承载任意数量的双向数据流。
数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。
这一特性,使性能有了极大提升:

同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应,消除了因多个 TCP 连接而带来的延时和内存消耗。
并行交错地发送多个请求,请求之间互不影响。
并行交错地发送多个响应,响应之间互不干扰。
在 HTTP/2 中,每个请求都可以带一个 31bit 的优先值,0 表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。

特性小结

Vite 带来的优势主要体现在提升开发者在开发过程中的体验。

1、Dev Server 无需等待,即时启动;
2、几乎实时的模块热更新;
3、所需文件按需编译,避免编译用不到的文件;
4、开箱即用,避免各种 Loader 和 Plugin 的配置;
TypeScript - 内置支持
less/sass/stylus/postcss - 内置支持(需要单独安装所对应的编译器)
Vite 的核心功能:Static Server + Compile + HMR

核心思路:

1、将当前项目目录作为静态文件服务器的根目录
2、拦截部分文件请求
3、处理代码中 import node_modules 中的模块
4、处理 vue 单文件组件(SFC)的编译
5、通过 WebSocket 实现 HMR

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容