Vite
vite 启动项目初体验
本文是学习bilibili这个视频时的笔记
在默认情况下,我们的 es module 去导入资源的时候,要么是绝对路径,要么是相对路径
浏览器不知道 node_modules, 所以不能使用包名导入
import _ from 'lodash'
js为什么浏览器不去搜寻 node_modules
因为,浏览器加载 js 都需要通过网络下载 js 文件。而一个库往往会依赖其他的库,这样对导致巨大的性能开销
vite 的预加载
import _ from 'lodash'
js在处理的过程中如果看到了有非绝对路径或者相对路径的引用,它会尝试开启路径补全
import __vite__cjsImport0_lodash from '/node_modules/.vite/deps/lodash.js?v=19679e9c'
js依赖预构建
首先 vite 会找对对用的依赖,然后调用 esbuild(对 js 语法进行解析的库), 将其转换成 es module, 然后放到/node_modules/.vite/deps
目录下, 同时对 es module 规范的各个模块进行统一
这解决了 3 个问题:
- 不同的第三方包会有不同的导出方式,这是 vite 所无法约束的
- 引入模块,对路径的处理上可以直接使用.vite/deps,方便路径重写
- 网络多包传输的性能问题(也是原生 es module 规范不敢支持 node_modules 的原因之一)
配置文件处理细节
- vite 配置文件的语法提示
- webstorm 自带提示
- vs code 的语法提示处理
// 第一种方式
import { defineConfig } from 'vite'
export default defineConfig({})
// 第二种方式
/** @type import("vite").UserConfig */
const viteConfig = {}
js- 关于环境的处理
export default defineConfig({ command } => {})
// commmand会区分生产环境和开发环境
// command 的值取决于,运行的命令是dev,还是build
js补充:为什么 vite.config.js 可以写成 es module 的形式
因为 vite 在读取 vite.config.js 时会率先用 node 解析文件语法,如果是 es module 会直接替换成 commonjs 规范
vite 环境变量配置
服务端
vite 使用 dotenv 库
dotenv 会自动读取.env 文件,并解析文件对应的环境变量,注入到 process.env 对象下
可以使用 loadEnv 手动加载
export default defineConfig(({ command, mode }) => {})
// mode为 pnpm dev --mode development --mode的参数
// mode默认情况下为development和production
js客服端
vite 会将环境变量注入到 import.meta.env
只会注入以VITE开头的变量
更改前缀,可以使用envPrefix配置
vite 中处理 css
vite 天生就支持对 css 文件的直接处理
- vite 在读取到 main.js 中引用到了 index.css
- 直接创建一个 style 标签,并插入到 index.html 的 head 中
- 将 css 文件中的内容替换成 js 脚本(方便热更新或者 css 模块化), 同时设置
Content-Type
为application/javascript
CSS 模块化会对所有类名进行一定规则的替换,防止协同开发时的类名冲突
vite 在生产环境对静态资源的处理
为什么打包后的静态资源有 hash
浏览器有缓存机制,静态资源只要不改名字,就直接走缓存,导致即使文件有更改,也没有请求最新的文件
vite 插件
vite 会在生命周期的不同阶段去调用不同的插件以达到不同的目的 生命周期:vite 从开始执行到执行结束,那么这整个过程就是 vite 的生命周期
当别人问道中间件、插件是干什么的? 中间件、插件会在生命周期的不同阶段去做不同的事情
ts
/// <reference types="vite/client" />
ts当 vite 读取到这个文件时会导入 vite/client 类型
vite 性能优化概述
-
开发时态的构建速度优化
-
页面性能指标:和我们怎么写代码有关
- 首屏渲染时
- 懒加载
- http 优化:协商缓存 强缓存
- 页面中最大元素的渲染时长: lcp(large content paint)
- 首屏渲染时
-
js 逻辑
-
清除副作用
-
requestIdleCallback requestAnimationFrame 卡浏览器帧率
-
防抖 节流
-
对作用域的控制
jsconst arr = [1, 2, 3]
// 每次访问arr 的length都是for循环自己的作用域
for (let i = 0, len = arr.length; i < len; i++) {}
jsconst arr = Array.from({ length: 10000 })
console.time('test1')
for (let i = 0; i < arr.length; i++) {}
console.timeEnd('test1')
console.time('test2')
for (let i = 0, len = arr.length; i < len; i++) {}
console.timeEnd('test2')
// test1: 0.182ms
// test2: 0.117ms
-
-
css
- 关注继承属性:能继承的,就不要重复写
- 尽量避免太过于深的 css 嵌套
-
生产的优化
- 优化体积:压缩,treeshaking,图片资源压缩,cdn 加载,分包
分包策略
业务代码变化,但是引用的库没有变,打包后的 js 文件每次都发生改变,导致性能损耗
把一些不会常规更新的文件,进行单独打包处理
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor'
}
}
}
},
}
jsgzip 压缩
vite 插件vite-plugin-compression
请求时的响应头设置为content-encoding: gzip
cdn 加速
将我们依赖的第三方模块全部写成 cdn 的形式,保证自己代码的小体积
vite 插件vite-plugin-cdn-import