关于vite基础阅读我上一篇文章# 一文了解vite基础
一、vite2 构建工具优缺点
传统工具开发环境构建方式和 vite 对比:
传统工具构建方式:
当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。
vite 构建方式:
Vite 通过在一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间。
依赖 大多为在开发时不会变动的纯 JavaScript。一些较大的依赖(例如有上百个模块的组件库)处理的代价也很高。依赖也通常会存在多种模块化格式(例如 ESM 或者 CommonJS)
Vite 将会使用 esbuild 预构建依赖。Esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。
源码 通常包含一些并非直接是 JavaScript 的文件,需要转换(例如 JSX,CSS 或者 Vue/Svelte 组件),时常会被编辑。同时,并不是所有的源码都需要同时被加载(例如基于路由拆分的代码模块)。
Vite 以 原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。
更新对比
在传统的工具(webpack)更新:
基于打包器启动时,重建整个包的效率很低。原因显而易见:因为这样更新速度会随着应用体积增长而直线下降。
一些打包器的开发服务器将构建内容存入内存,这样它们只需要在文件更改时使模块图的一部分失活[1],但它也仍需要整个重新构建并重载页面。这样代价很高,并且重新加载页面会消除应用的当前状态,所以打包器支持了动态模块热重载(HMR):允许一个模块 “热替换” 它自己,而不会影响页面其余部分。这大大改进了开发体验 —— 然而,在实践中我们发现,即使采用了 HMR 模式,其热更新速度也会随着应用规模的增长而显著下降。
vite 更新:
在 Vite 中,HMR 是在原生 ESM 上执行的。当编辑一个文件时,Vite 只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失活[1](大多数时候只是模块本身),使得无论应用大小如何,HMR 始终能保持快速更新。
Vite 同时利用 HTTP 头来加速整个页面的重新加载(再次让浏览器为我们做更多事情):源码模块的请求会根据 304 Not Modified 进行协商缓存,而依赖模块请求则会通过 Cache-Control: max-age=31536000,immutable 进行强缓存,因此一旦被缓存它们将不需要再次请求。
vite 一些缺点:
- vite 推出时间太短了,生态这块没有其他构建工具那么完善,同时很多问题和述求没有暴露出来
- 针对代码合并切割这块功能没有 webpack 强大(微前端, 代码切割)
二、resolve 解析
和 webpack 类似,resolve 字段用来表示如何来解析模块,首先我们看下常用的别名设置 alias
import { defineConfig, loadEnv } from 'vite'
export default ({ mode, command }) => {
console.log(loadEnv(mode, process.cwd()).VITE_APP_BASE_PATH, 'base-path')
return defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'), // 设置 `@` 指向 `src` 目录
}
}
})
}
复制代码
这样我们就能用@替换相对路径了,可以通过@来引入组件:
import Pagination from '@/components/pagination/index.vue'
复制代码
三、按需引入
我们在使用 element 时,经常会需要按需引入组件,在 vue-cli 中使用的是 babel 的一个插件 babel-plugin-component;vite 有自己的按需引入插件 vite-plugin-style-import,首先我们安装一下:
npm install vite-plugin-style-import -D
复制代码
然后在 vite.config.js 中进行配置
import styleImport from "vite-plugin-style-import";
export default defineConfig({
plugins: [
vue(),
styleImport({
libs: [
{
libraryName: "element-plus",
esModule: true,
ensureStyleFile: true,
resolveStyle: (name) => {
return `element-plus/lib/theme-chalk/${name}.css`;
},
resolveComponent: (name) => {
return `element-plus/lib/${name}`;
}
}
]
})
]
})
复制代码
接下来如果我们只希望引入部分组件,就可以在 main.js 中加入:
import { ElButton, ElSelect } from 'element-plus'
const app = createApp(App)
app.component(ElButton.name, ElButton)
app.component(ElSelect.name, ElSelect)
复制代码
四、gzip 压缩
插件安装
npm install vite-plugin-compression -D
# or yarn
yarn add vite-plugin-compression -D
复制代码
用法:
import viteCompression from 'vite-plugin-compression'
import { defineConfig, loadEnv } from 'vite'
export default ({ mode, command }) => {
return defineConfig({
plugins: [
viteCompression()
],
})
}
复制代码
五、文件打包分析
插件安装
npm install rollup-plugin-visualizer -D
# or yarn
yarn add rollup-plugin-visualizer -D
复制代码
用法:
import { visualizer } from 'rollup-plugin-visualizer'
import { defineConfig, loadEnv } from 'vite'
export default ({ mode, command }) => {
return defineConfig({
build: {
rollupOptions: {
plugins: [
visualizer({ open: true, gzipSize: true })
]
}
}
})
}
复制代码
六、将外部导入转换为全局变量,打包把模块排除
插件安装
npm install -D rollup-plugin-external-globals
# or yarn
yarn add rollup-plugin-external-globals -D
复制代码
用法:
import externalGlobals from 'rollup-plugin-external-globals'
import { defineConfig, loadEnv } from 'vite'
export default ({ mode, command }) => {
return defineConfig({
build: {
rollupOptions: {
external: ['vue', 'vuex', 'vue-router', 'axios', 'ElementPlus'],
plugins: [
externalGlobals({
vue: 'Vue',
'element-plus': 'ElementPlus',
'vue-router': 'VueRouter',
vuex: 'Vuex',
axios: 'axios'
})
]
}
}
})
}
复制代码
七、vite 使用 rollup 插件
一般来说,只要一个 Rollup 插件符合以下标准,那么它应该只是作为一个 Vite 插件:
- 没有使用 moduleParsed 钩子。
- 它在打包钩子和输出钩子之间没有很强的耦合。
- 如果一个 Rollup 插件只在构建阶段有意义,则在 build.rollupOptions.plugins 下指定即可。
建议在不确定是否能用的情况下使用 Vite 专属的插件:
- Vite 插件应该有一个带 vite-plugin- 前缀、语义清晰的名称。
- 在 package.json 中包含 vite-plugin 关键字。
- 在插件文档增加一部分关于为什么本插件是一个 Vite 专属插件的详细说明(如,本插件使用了 Vite 特有的插件钩子)。
八、热更新
热更新(hot module replacement) ,简称 hmr
,是一种无需刷新浏览器即可更新代码效果的技术,实现该技术的关键点是要建立 浏览器 和 服务器 之间的联系,还好我们现成就有一种技术可以实现:websocket
协议,普通的 http
协议为短连接,一次会话结束就会关闭,这显然没法满足我们时刻都需要关联 浏览器 和 服务器 的需求,而websocket
为长连接,可以一直保持 浏览器 和 服务器 之间的会话不中断,通过事件来互相传送数据,vite
也用了 websocket
来实现 热更新。
热更新主体流程如下:
- 服务端基于 watcher 监听文件改动,根据类型判断更新方式,并编译资源
- 客户端通过 WebSocket 监听到一些更新的消息类型
- 客户端收到资源信息,根据消息类型执行热更新逻辑
九、❤️感谢阅读
- 如果本文对你有帮助,不要吝啬你的赞哟,你的「赞」是我前行的动力。
- 欢迎关注公众号 【前端冥想】 ,也可扫码加我微信备注 【加群】 拉你进交流分享群,一起学习进步。