vite项目中的常见问题
开始在个人项目中全量使用vite
了,使用了一段时间,感觉开发体验确实很好。本文主要整理了vite项目中的一些常见问题及解决办法。
自动引入
减少重复的import
模块引入代码
全局API
在很多文件中都需要引入一些框架API,如Vue的ref
、onMounted
等代码,写多了就感觉很重复,可以试试unplugin-auto-import
import AutoImport from 'unplugin-auto-import/vite'
const plugins = [
AutoImport({
// 定义需要自动引入的框架
imports: ['vue', 'vue-router'],
// 处理eslint
eslintrc: {
enabled: true,
},
}),
]
该插件会自动生成一个auto-imports.d.ts
,然后添加到tsconfig.json
的include
中
接着就可以直接写代码,无需再重复引入了
const a = ref(0)
项目如果使用了eslint
,可能会提示某些API未引入的错误,这时候可以开启eslintrc.enabled
配置项.
这个配置项打开后,会在项目目录生成.eslintrc-auto-import.json
文件(实际上就是把自动引入的API声明为globals
全局变量)
最后,在.eslintrc.js
文件中exteneds
配置项把这个文件包括进来就可以了
module.exports = {
extends: [
'plugin:vue/vue3-essential',
'airbnb-base',
'plugin:@typescript-eslint/recommended',
'./.eslintrc-auto-import.json', // 这一行
],
}
组件库
引入组件库的时候,出于性能考虑,往往需要实现按需引入相关组件,主流的UI库也提供了相关的插件如babel-plugin-component
(ElementUI)等来实现,在vite中可以通过unplugin-vue-components
来实现
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
// ...
plugins: [
// ...
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
之后就再无需手动引入组件的情况下就可以直接使用组件了
<template>
<el-button>click</el-button>
</template>
<script lang="ts" setup>
// 无需每个组件都显示引入该UI组件了
// import {ElButton} from 'element-plus'
</script></script>
resolvers
内置了十来种主流UI库的按需加载解析器,如果有未包含在内的组件库,也可以很简单的实现一个
Components({
resolvers: [
// example of importing Vant
(componentName) => {
// where `componentName` is always CapitalCase
if (componentName.startsWith('Van'))
return { name: componentName.slice(3), from: 'vant' }
},
],
})
MFC多组件文件
Vue默认的组件形式是SFC (Single File Component
),一个文件只能对应一个组件,对于某些UI组件创建单个SFC显得有点繁琐。
因此可以考虑下面这种通过tsx实现的MFC组件,即一个文件里面有多个组件
首先需要安装@vitejs/plugin-vue-jsx
支持tsx
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
plugins: [vue(),vueJsx()],
})
然后就可以编写tsx
文件了
// 使用css module
import styles from './comp.module.scss'
type Demo1Props = {
msg: string
}
export const Demo1 = defineComponent({
props: ['msg'],
setup(props: Demo1Props) {
return () => (<div class={styles.demo1}>demo1 {props.msg}</div>)
},
})
type Demo2Props = {
initValue: number
}
export const Demo2 = defineComponent({
props: ['initValue'],
setup(props: Demo2Props) {
const count = ref(props.initValue)
const add = () => {
count.value++
}
return () => (<div onClick={add}>demo2 {count.value}</div>)
},
})
在其他的SFC组件中,可以直接引入这个文件里的小组件,维护起来要方便很多,缺点就是无法使用SFC的setup 语法糖等功能,有舍有得。
css原子类
原子类大法,在某些场景下还是有点香(但不是万能的~
目前主流的原子类方案都支持了vite,以windicss为例
安装
npm i -D vite-plugin-windicss windicss
在vite.config.ts
中引入插件
import WindiCSS from 'vite-plugin-windicss'
export default {
plugins: [
WindiCSS(),
],
}
在入口文件main.ts
引入虚拟模块
import 'virtual:windi.css'
然后就可以愉快地编码了。
vitest单元测试
vitest是vite项目首选的单元测试框架,当然也可以在非vite项目的环境下直接使用,相信我,体验了之后你就会喜欢上单元测试了。
跟所有测试框架类似,默认约定x.test.ts
的文件为测试文件
// util.test.ts
import {describe, it, expect} from "vitest"
import {add} from './util'
describe("util test", () => {
it("100% pass", () => {
expect(1 === 1)
})
it("add", () => {
expect(add(1, 2)=== 3)
})
})
然后运行vitetest
即可,更通用的方案是修改package.json的test
命令
"scripts": {
"test": "vitest"
}
除了常规的测试文件用例之外,vitest还支持源码内联测试、类型测试等高级功能,快去试一下~
CDN上传构建产物
对于构建之后的资源发布到CDN,有两种处理方式
- 构建结束后,通过oss sdk直接将文件上传到CDN
- nginx转发资源路径,通过CDN配置文件回源地址
第一种方式更加灵活,更容易在项目中落地。
社区提供了类似于vite-plugin-ali-oss之类的插件,不过在使用中发现一些不尽人意的地方,因此这里不介绍插件的使用方式,而是大概的实现思路
相关的实现也比较简单
- 插件注册closebundle的钩子,
- 这个函数调用时可认为构建已结束,读取输出目录下的所有文件
- 遍历文件夹和文件,调用oss sdk(比如常见的阿里云、七牛等)上传文件
由于sdk上传文件时需要秘钥等,如果担心直接明文写在vite.config.ts
中不太方便权限管理,也可以放在CI中通过环境变量的形式注入。
小结
本文主要整理了vite项目中一些常见的功能,后面会继续补充。
你要请我喝一杯奶茶?
版权声明:自由转载-非商用-保持署名和原文链接。
本站文章均为本人原创,参考文章我都会在文中进行声明,也请您转载时附上署名。