体验一把Vite
# vite和webpack的区别
vite优点:快速冷启动、按需编译、模块热更新
webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。 而vite是直接启动开发服务器,请求哪个模块再对该模块进行实时编译。
现代浏览器本身就支持ES Module,会自动向依赖的Module发出请求。 vite利用这一点,将开发环境下的模块文件,就作为浏览器要执行的文件,vite在启动的时候不需要打包,不需要分析模块的依赖和编译,因此启动速度快。
当浏览器请求某个模块时,再根据需要对模块内容进行编译。按需动态编译缩减了编译时间。 在浏览器请求路由时才会进行打包,而且也仅仅打包当前路由的源码,这相当于让浏览器掌握了打包的控制权。从而将Bundle based dev server一次性打包全部源码的操作改为了多次
HMR方面,当改动了一个模块后,仅需让浏览器重新请求该模块,而webpack需要把该模块的相关依赖模块全部编译一次,效率更高。
Webpack 的热更新会以当前修改的文件为入口重新 build 打包,所有涉及到的依赖也都会被重新加载一次。虽然webpack 也采用的是局部热更新并且是有缓存机制的,但是还是需要重新打包所以很大的代码项目是真的有卡顿的现象
文件缓存:Vite 会将预构建的依赖缓存到node_modules/.vite。它根据几个源来决定是否需要重新运行预构建步骤:package.json中的 dependencies列表, package-lock等 浏览器缓存:源码模块的请求会根据 304 Not Modified 进行协商缓存,而依赖模块请求则会通过 Cache-Control: max-age=31536000,immutable 进行强缓存
# 缺点
生态不如webpack:wepback的loader和plugin非常丰富
prod环境的构建用Rollup:esbuild对于css和代码分割不是很友好
vite的主要优势在开发阶段。另外,由于vite利用的是ES Module,因此在代码中不可以使用CommonJS
# Vite 的原理
Vite 实现的核心——拦截浏览器对模块的请求并返回处理后的结果。
浏览器发起的第一个请求 localhost:3000/,发送到 Vite 后端之后经过静态资源服务器的处理,会进而请求到 index.html,Vite对这个请求做拦截和处理了
把原本一个 .vue 的文件拆成了2个请求(分别对应 template和script、style ) ,浏览器会先收到包含 script和template 逻辑的 App.vue 的响应,然后解析到 style 的路径后,会再次发起 HTTP 请求来请求对应的资源,此时 Vite 对其拦截并再次处理后返回相应的内容。
- vite1: 使用的是 koa
- vite2: 使用的是 Connext; Connext更加是个转发
请求服务器 --> 获取自己的代码 --> Connext拦截 -->vite工具处理成 es6.js代码---> Connext转发--->发送给浏览器
# ESBuild
vite打包快:基于ESBuild,ESbuild 是一个类似webpack构建工具。
- ESBuild为什么这么快?
- 使用GO语言编写的, 可以直接转换成机器代码, 而无需经过字节码;
- ESBuild利用CPU的多内核,尽可能饱和运行;
- ESBuild的所有内容都是从零开始编写的,而不是使用第三方,考虑各种性能问题;
- Vite生产环境为什么选择Rollup做构建工具。
- Vite是一个由原生ESM驱动的Web开发构建工具。在选择构建工具的时候也最好可以选择基于ESM的工具。
- Rollup是基于ES2015的JavaScript打包工具。 它将小文件打包成一个大文件或者更复杂的库和应用,打包既可用于浏览器和Node.js使用。 Rollup最显著的地方就是能让打包文件体积很小。相比其他JavaScript打包工具,Rollup总能打出更小,更快的包。
- 因为Rollup基于ES2015模块,比Webpack和Browserify使用的CommonJS模块机制更高效。
rollup打包生成代码的构建比较简单,总的流程的是先调用rollup.rollup()从入口开始编译,建立依赖关系图, 然后调用bundle.write()或bundle.generate()输出代码,其中bundle.write()会将代码输出到磁盘中。
# vite 搭建项目
npm create vite@latest my-vue-app -- --template vue
cd my-vue-app
npm install
// 或者
npm install -g create-vite-app
create-vite-app my-vue-app
cd my-vue-app
npm install
2
3
4
5
6
7
8
9
10
- vite.config.js常用配置
import { defineConfig } from 'vite'
import { resolve } from "path"; // 主要用于alias文件路径别名
import vue from '@vitejs/plugin-vue'
import vueJsx from "@vitejs/plugin-vue-jsx"; // jsx插件
export default defineConfig({
plugins: [vue(), vueJsx()], // 插件列表
base: './', // 在生产中服务时的基本公共路径。
resolve: {
alias: { "@": path.resolve(__dirname, './src'), } // 配置别名
},
// 引入第三方的配置,强制预构建插件包
optimizeDeps: { include: ['echarts', 'axios', 'mockjs'], },
// 打包配置
build: {
target: 'modules', // 最终构建的浏览器兼容目标。modules:支持原生 ES 模块的浏览器
outDir: 'dist', // 指定输出路径
assetsDir: 'assets', // 指定生成静态资源的存放路径
sourcemap: false, // 构建后是否生成 source map 文件
minify: 'terser' // 混淆器,terser构建后文件体积更小
},
// 本地运行配置,及反向代理配置
server: {
host: 'localhost', // 指定服务器主机名
port: 3000, // 指定服务器端口
open: true, // 在服务器启动时自动在浏览器中打开应用程序
strictPort: false, // false-- 若端口已被占用则会尝试下一个可用端口,而不是直接退出
https: false, // 是否开启 https
cors: true, // 为开发服务器配置 CORS。默认启用并允许任何源
proxy: { // 为开发服务器配置自定义代理规则
'/foo': 'http://192.168.xxx.xxx:xxxx',
'/api': {
target: 'http://192.168.xxx.xxx:xxxx', //代理接口
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39