vite是什么
vite是尤大在更新vue3之后,再次开发的一个新的构建工具。那什么构建工具让尤大在过年都在疯狂更新呢?它到底有什么魔力呢?
在vite开发出来之后,就连webpack团队的核心成员都在感叹
Vite(法语意思是 “快”,发音为 /vit/,类似 veet)是一种全新的前端构建工具。你可以把它理解为一个开箱即用的开发服务器 + 打包工具的组合,但是更轻更快。Vite 利用浏览器原生的 ES 模块支持和用编译到原生的语言开发的工具(如 esbuild)来提供一个快速且现代的开发体验。
构建工具的前世今生
构建工具的作用
构建工具:用来让我们不再做机械重复的事情,解放我们的双手的。
在早期开发过程中。有很多令我们不爽的地方
-
- js是弱类型
-
- 手动维护依赖很麻烦
-
- 浏览器的兼容性
-
- 没有热更新
.......
于是 前端构建工具应运而生。构建工具可以帮助我们做以下工作
-
- 代码检查
-
- 代码压缩,混淆
-
- 依赖分析,打包
-
- 语言编译(比如ts转化js,scss转化css)
...
在了解vite之前我们先了解一下其他的构建工具,这样我们才能更好的对比vite的强大之处。
前端的构建工具有很多。比如 Grunt Gulp FIS3 Webpack Rollup Parcel snowpack vite
接下来我会挑几个构建工具进行简单的介绍
常见的打包工具的工作流
Gulp
Gulp.js 是一个自动化构建工具,开发者可以使用它在项目开发过程中自动执行常见任务。Gulp.js 是基于 Node.js 构建的,利用 Node.js 流的威力,你可以快速构建项目
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
// Lint JS
gulp.task('lint', function() {
return gulp.src('src/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
// Concat & Minify JS
gulp.task('minify', function(){
return gulp.src('src/*.js')
.pipe(concat('all.js'))
.pipe(gulp.dest('dist'))
.pipe(rename('all.min.js'))
.pipe(uglify())
.pipe(gulp.dest('dist'));
});
// Watch Our Files
gulp.task('watch', function() {
gulp.watch('src/*.js', ['lint', 'minify']);
});
// Default
gulp.task('default', ['lint', 'minify', 'watch']);
gulp的执行是从上倒下的执行一个个任务。然后文件内容通过管道。进行传递。如果你想了解更多gulp的知识,可以去gulp官网
Webpack
webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle。
接下来我们看看Webpack的工作原理图
从上图我们可以看出webpack打包分为一下步骤
-
-
查找入口文件
从webpack的配置文件中查找entry的配置,从而找到入口文件
-
-
-
分析依赖关系
接到入口文件之后,从入口文件出发,分析入口文件中依赖了哪些文件,并且这些依赖的文件中还可能依赖别的文件,就这么递归的找下去。
-
-
-
模块函数
找到依赖中的所有文件,把这些文件转化成模块的函数,为了方便后面webpack进行调用
-
-
-
打包
打包完毕的文件可以产出到配置文件的output指定路径里,生成一个bundle
-
-
-
启动服务
node创建本地服务器并启动静态页面
-
这大概是我们webpack在开发环境打包的主要流程。
熟悉了我们常见的打包工具的工作流。接下来我们看看vite是怎么工作的。 看看vite为什么被称为下一代开发和构建工具。
vite的原理和优势
目前打包工具的困境
在目前的工作中,我们主要利用webpack+vue(webpack+react)进行项目开发。然而,当我们构建越来越大型的应用的时候,打包工具需要处理的javascript代码量也呈指数级增长。在大型项目中包含几百甚至几千个模块的情况也越来越多。我们开始遇到性能瓶颈,使用javascript的工具通常需要很长的时间,才能启动开发服务器
这是我工作中的一个真实项目, 项目不大,但是启动服务器的时间花了30s。这作为一个讲究效率的程序员肯定是无法忍受的
当项目越来越大,项目的hrm热更新速度越来越慢。有时候甚至改动一个字段,页面几十秒之后才会进行热更新。
为什么会产生这种问题
其实这和webpack打包的原理有关系,我们前面其实已经大概了解webpack的主要工作流,这里就不在详细讲解
- 启动服务器慢,是因为在每次服务器启动之前。webpack需要执行一系列的事情。找模块间的依赖,将各个模块进行合并,生成一个build,存入内存中,最后在启动服务器。所以速度上随着项目的增加,速度会越来越慢
- webpack的hrm。当你改动一个文件的时候,Webpack 的热更新会以当前修改的文件为入口重新 build 打包,所有涉及到的依赖也都会被重新加载一次。所以速度也随着项目的增加而降低(后面会写一遍文章专门介绍webpack的hrm的实现)
......
vite的优势
vite的三大特点
-
- 快速的冷启动 在开发预览中,它是不进行打包的。
-
- 即时热模块更新(HMR,Hot Module Replacement)
-
- 真正按需进行加载
当然vite也有一定的问题,
-
vite的生态还不够完善。
-
在生产模式下仍然需要打包。尽管原生 ESM 现在得到了广泛支持,但由于嵌套导入会导致额外的网络往返,在生产环境中发布未打包的 ESM 仍然效率低下(即使使用 HTTP/2)。为了在生产环境中获得最佳的加载性能,最好还是将代码进行 tree-shaking、懒加载和 chunk 分割(以获得更好的缓存)。
vite的原理
通过上面的了解,我们已经知道了利用vite的很多优势,那么接下来我们看看vite是怎么实现的。
ES Modules
vite的成功得益于现代浏览器对于基于ECMAScript 标准原生模块系统(ES Modules)实现。 目前主流浏览器(IE11除外)都已经支持。他允许我们在浏览器使用export、import 的方式导入和导出模块,在 script 标签里设置 type="module"
<script type="module">
import { createApp } from './main.js‘
createApp()
</script>
浏览器会识别添加type="module"的 <script>
元素,浏览器会把这段内联 script 或者外链 script 认为是 ECMAScript 模块。然后浏览器会被这里面的import引用发起一个http请求,请求获取文件中的内容。
因此我们对于第三方的模块,可以不用打包合并,而是通过import 这种方式去发起http 请求,获取代码。这也是vite的主要实现思路。
如果你对ES Modules 不够了解。可以去看看ES Modules的规范
vite的工作流和冷启动
首先看一张图
- 首先是启动一个静态资源服务器
- 找到项目的入口,开始加载入口文件
- 当声明一个 script 标签类型为 module 时,浏览器就会像服务器发起一个GET
- Vite 通过劫持浏览器
劫持浏览器
劫持浏览器的这些请求,并在后端进行相应的处理,将项目中使用的文件通过简单的分解与整合,然后再返回给浏览器。
从上面的分析可知: vite主要做了以下事情
-
- 启动了一个静态资源服务器
-
- 只需要在浏览器请求源码时进行转换并按需提供源码
vite整个过程中没有对文件进行打包编译,至于其他加载的工作就交给了浏览器,所以其运行速度比原始的webpack开发编译速度快出许多。
vite的热更新
传统打包器是将项目打包之后的资源存入电脑的内存之中,这样他们只需要在文件更改的时候,将对应的模块进行失活,但是它仍然需要重新构建并重载页面。 所以像webpack这类的打包工具支持了动态模块热重载(HRM),允许一个模块替换自己,而对其余页面没有影响。但是在实践中。我们发现HRM的速度会随着项目的增大而降低(原因在 目前打包工具的困境
这一节已经分析过了)
而在vite中HMR 是在原生 ESM 上执行的。当编辑一个文件时,Vite 只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失效(大多数时候只需要模块本身),使 HMR 更新始终快速,无论应用的大小。
vite的按需加载
为什么说vite才是真正的按需加载呢?难道webpack不是真正的按需加载吗?
如果你想知道,那么你可以看看去看看webpack的原理,这里我简单介绍一下
webpack其实在开始构建打包的时候,还是对所有的文件进行一次打包构建,只是在webpack遇到 import( * ) 这种语法的时候,会另外生成一个chunk; 只有在合适的时候去加载import中的内容
从上面的分析可以知道。不管我们这段import的代码何时执行,我们对需要对它进行一定的打包
但是vite不一样,只有在你真正的需要加载的时候,浏览器才会发送import请求,去请求文件中的内容,所以才说vite才是真正的按需加载
实现一个基础版vite
我们已经知道了vite的大概工作原理,那么我们接下来实现一个最基础的vite
vite和webpack编译过后文件的区别
webpack编译后的文件
vite编译后的文件
main.js
第一步: 从上图我们可以看出vite首先也是找到一个入口文件,然后修改一些依赖模块的路径,比如把vue替换成了/@modules/vue.js. 把./App.vue替换成了绝对路径
第二步: 首先去寻找第一个组件App.vue。将App.vue中的js复制给一个常量,然后在App.vue中的html转化为一个render函数,挂载到js的那个常量身上。
实现我们自己的vite
首先我们初始化一个项目
npm init vite-app <project-name>
cd <project-name>
npm i
npm run dev
这样我们就能成功启动一个vite+vue的项目。 接下来我们不用vite,自己来实现一个我们自己的vite
新建yj-vite.js文件 从上图我们对vite分析可以得知,实现vite主要有以下几个步骤
搭建一个服务器
我们这里主要使用koa来实现
然后执行 node yj-vite.js
可以看到,这样一个静态资源服务器就已经搭建成功了
拦截请求,替换模块
如果我们请求的是首页,那么我们拿到绝对地址,进行拼接,读取文件,并返回,如果不是,我们就直接读取文件。并返回
这时候我们看到请求其实已经成功,但是控制台报了一个错误
原因是浏览器不能识别 import ..form 'vue' 要把vue变成一个绝对路径地址
更换路径
所以我们需要对上一步的内容进行改造,当以js结尾的文件中包含import 加载第三方模块的时候,我们首先将
```
import vue from 'vue'
替换
import vue from '/@modules/vue'
```
这样我们就可以看到main.js中已经成功替换了
那么接下来看看我们怎么处理 /@module/vue
这样我们就能正确处理第三方模块了。并且第三方模块也已经成功加载了。
但此时浏览器中会有一个错误
这是因为在vue的源码中,是有process.env这个环境变量,所以在index.html中我们可以加下以下内容,进行简单处理一下。
<script>
window.process = {
env: {
NODE_ENV: 'dev'
}
}
</script>
这样我们就能够成功执行。
识别vue文件
但是在我们main.js中一般都不会这样写
createApp({
render: () => h('div','3333333')
}).mount('#app')
而是通过单文件组件的形式去编写代码
import App from './App.vue'
createApp(App).mount('#app')
那么我们怎么去识别.vue中文件的内容,并且成功获取呢
这里简单说一下接下来的大概思路
- 匹配.vue结尾的文件,读取其中的js代码 把
export default
替换成const __script =
- 将渲染过后template相关的部分挂在到
__script
下
这样我们就成功手写了一个vite
总结
源码地址
github.com/yujun96/myv…
vite
其实官方的vite远远比这个复杂。在http请求之前,其实vite做了一个预打包,预打包的目的是为了减少http请求,因为可能一个模块依赖了成百上千个模块,过多的请求增大了浏览器的负担。 如果你想了解vite怎么实现预打包,你可以看看esbuild
当然vite怎么实现按需加载, 热更新 ... 等等功能,你可以关注我,等待后续更新
后续更新内容
vite 下一代前端开发与构建工具(二)
主要内容: vite更多功能的实现,以及如何将vue2项目迁移到vite
webpack hrm的实现原理
主要内容: 主要讲解webpack中hrm的底层实现
vue2 vue2的原理
主要内容: MVVM的实现 虚拟dom diff算法等等
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!