摘要:在现代前端开发中,构建一个高效、可维护且易于协作的开发环境至关重要。特别是在开发Vue3组件库时,我们需要确保代码的质量、一致性和文档的完整性。本文将带你从0搭建vue3组件库开发环境,以下是配置代码规范、格式化、CSS样式工具、文档工具、单元测试技术选型的必要性。
为什么引入ESLint和Prettier
- ESLint:它是一个代码检查工具,可以帮助我们在编译前就能发现代码中的潜在问题,如未使用的变量、可能的逻辑错误等。通过配置ESLint,我们可以强制执行团队的代码风格和最佳实践,从而提高代码质量。
- Prettier:作为一个代码格式化工具,Prettier可以自动调整代码的格式,确保所有代码遵循统一的格式标准。这不仅有助于提升代码的可读性,还能减少因格式问题引起的代码审查冲突。
为什么引入Sass和Tailwind CSS
- Sass:作为一种CSS预处理器,Sass提供了变量、嵌套规则、混合(mixins)等特性,使得CSS的编写更加高效和模块化。它有助于我们更好地组织和管理样式代码。
- Tailwind CSS:这是一个实用程序优先的CSS框架,它提供了一系列的类,可以直接在HTML中使用,快速构建界面。Tailwind CSS的灵活性和响应式设计使其成为快速原型开发和迭代的理想选择。
使用VitePress编写组件文档
- VitePress:Vue.js的官方静态站点生成器,专为文档和博客设计。它基于Vue3和Vite,提供了简洁的Markdown语法和Vue组件的集成,使得编写和维护组件文档变得简单直观。良好的文档对于组件库的用户来说至关重要,它可以帮助用户快速理解和使用组件。
配置单元测试工具Vitest
- Vitest:这是一个基于Vite的测试框架,它提供了快速的测试运行速度和良好的开发体验。通过编写单元测试,我们可以确保组件的每个部分都能按预期工作,减少bug的产生,提高代码的健壮性。
通过引入这些工具和库,我们不仅能够提升开发效率,还能确保代码的质量和一致性。ESLint和Prettier保证了代码风格的一致性,Sass和Tailwind CSS加速了样式开发,VitePress简化了文档编写,而Vitest则确保了组件的可靠性。这些工具的结合使用,为Vue3组件库的开发提供了一个全面、高效的解决方案。
假设在本博客前你已经看过必备知识导学了
Vue3组件库开发项目实战——01组件开发必备知识导学-CSDN博客
创建vite项目
用vite首先创建一个支持ts的项目:使用命令 npm create vite或yarn create vite
设置一个项目名称,并选择Vue+TypeScript
安装JSX
在Vite项目中引入JSX,我们可以通过@vitejs/plugin-vue-jsx插件实现,首先安装它:
使用命令:npm i @vitejs/plugin-vue-jsx -D 或 yarn add @vitejs/plugin-vue-jsx -D
配置JSX
配置一下该插件,在vite.config.ts配置文件中
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()],
});
安装ESLint
ESLint:用于代码风格检查和规范。使用下面命名:确保不会因为版本号冲突
npm install @typescript-eslint/eslint-plugin@^5.7.0 @typescript-eslint/parser@^5.7.0 eslint@^8.5.0 eslint-plugin-vue@^8.2.0 --save-dev
配置.eslintrc.js
在项目根目录创建一个 .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
"vue/setup-compiler-macros": true,
},
extends: [
"eslint:recommended",
"plugin:vue/essential",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-recommended",
],
parserOptions: {
ecmaVersion: 13,
parser: "@typescript-eslint/parser",
sourceType: "module",
},
plugins: ["vue", "@typescript-eslint"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
"vue/no-multiple-template-root": "off",
"vue/max-attributes-per-line": "off",
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline": "off",
"vue/html-self-closing": "off",
},
};
运行ESlint
然后在 package.json 的
scripts
中添加 ESLint 的运行命令 "lint": "eslint . --ext .ts,.vue"
运行npm run lint
将第五行删除,解决报错
安装Prettier
使用命令:npm i -d prettier eslint-plugin-prettier eslint-config-prettier
或者
yarn add -D prettier eslint-plugin-prettier eslint-config-prettier
配置.prettierrc.js
创建一个 prettier.config.js 文件
module.exports = {
// printWidth: 80,
// tabWidth: 2,
// useTabs: false,
semi: false, // 未尾逗号, default: true
singleQuote: true, // 单引号 default: false
// quoteProps: 'as-needed',
// jsxSingleQuote: false,
trailingComma: "none", // 未尾分号 default: es5 all | none | es5
// bracketSpacing: true,
// bracketSameLine: false,
// jsxBracketSameLine: false,
arrowParens: "avoid", // default: always
// insertPragma: false,
// requirePragma: false,
proseWrap: "never",
// htmlWhitespaceSensitivity: 'css',
// vueIndentScriptAndStyle: false, // .vue 缩进
endOfLine: "auto", // default lf
};
修改.eslintrc.js文件
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
'vue/setup-compiler-macros': true
},
extends: [
'eslint:recommended',
'plugin:vue/essential',
'plugin:@typescript-eslint/recommended',
'plugin:vue/vue3-recommended',
'plugin:prettier/recommended'
],
parserOptions: {
ecmaVersion: 13,
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: ['vue', '@typescript-eslint'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'vue/no-multiple-template-root': 'off',
'vue/max-attributes-per-line': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/html-self-closing': 'off',
'prettier/prettier': 'off'
}
}
解决可能的 Delete `␍`eslint(prettier/prettier)问题
git config --global core.autocrlf false
安装VitePress
使用命令:npm add -D vitepress 或 yarn add -D vitepress
Getting Started | VitePress vitepress api文档 Getting Started | VitePress
vitepress目录初始化
使用npx vitepress init命令初始化vitepress项目目录结构
项目目录如下
启动vitepress
初始化后scripts会自动添加如下vitepress启动脚本
{
"scripts": {
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:serve": "vitepress serve docs",
"docs:preview": "vitepress preview docs"
}
}
输入命令:npm run docs:dev
浏览器打开地址,可以看到通过npx vitepress init初始化后的的内容已经渲染到vitepress页面了
安装Sass + Tailwind CSS
使用命令
npm install -D sass tailwindcss postcss autoprefixer
tailwindcss配置初始化
npx tailwindcss init -p
配置Tailwind CSS
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
theme: {
extend: {}
},
plugins: []
}
新增src/index.scss文件
/* index.scss */
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
在main.ts中引入tailwindcss样式文件
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import './index.scss'
createApp(App).mount('#app')
可以通过vite的示例components中测试一下tailwind css是否可以用
打开浏览器可以看到样式已经生效了
Tailwind css常用样式
Tailwind CSS 是一个高度可定制的 CSS 框架,提供了丰富的实用类,可以帮助快速构建现代化的网页界面。以下是一些 Tailwind CSS 中常用的样式类:
-
布局类:
container
: 设置页面内容的最大宽度并居中显示。mx-auto
: 水平居中。my-auto
: 垂直居中。flex
: 创建弹性布局。grid
: 创建网格布局。
-
间距类:rem是根元素的fontsize
m-4
: 设置外边距为 1rem。p-4
: 设置内边距为 1rem。mx-8
: 设置水平外边距为 2rem。my-8
: 设置垂直外边距为 2rem。
-
字体类:
text-sm
: 设置字体大小为小号。font-bold
: 设置字体为粗体。text-center
: 文本水平居中显示。text-gray-500
: 设置文本颜色为灰色。
-
背景类:
bg-gray-200
: 设置背景颜色为灰色。bg-cover
: 背景图像覆盖整个元素。bg-center
: 背景图像居中显示。
-
边框类:
border
: 添加边框。border-gray-300
: 设置边框颜色为灰色。rounded-md
: 添加圆角边框。
-
响应式类:
sm:text-lg
: 在小屏幕上设置文本大小为大号。md:hidden
: 在中等屏幕上隐藏元素。
这些只是 Tailwind CSS 中一部分常用样式类,Tailwind CSS 还提供了许多其他实用类,可以根据具体需求灵活使用。Tailwind CSS 的特点是通过组合这些类来构建界面,避免了手动编写大量的 CSS 样式,提高了开发效率。
安装vitest
npm install -D vitest happy-dom @testing-library/vue
vitest
: 测试框架,用于执行整个测试过程并提供断言库、mock、覆盖率happy-dom
: 是用于提供在 Node 环境中的 Dom 仿真模型
配置vite.config.ts
在配置时,我们发现 ts文件会报错。这是由于 test 属性属于 Vitest
的扩展属性,vite
原生配置中并没有定义这个属性。在vite.config.ts顶部加上///注释
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()],
test: {
globals: true,
environment: 'happy-dom',
// 支持tsx组件,很关键
transformMode: {
web: [/\.[jt]sx$/]
}
}
})
配置vitest启动命令
在script脚本中添加
"test": "vitest",
"coverage": "vitest run --coverage"
测试vitest
来测试一下vitest的效果吧,随意创建sum.js文件和sum.test.js文件
// sum.js
export function sum(a, b) {
return a + b
}
// sum.test.js
import { expect, test } from 'vitest'
import { sum } from './sum'
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3)
})
简单解析这段代码:
import { expect, test } from 'vitest'
: 这行代码从 'vitest' 模块中导入了expect
和test
两个函数。expect
用于编写断言,test
用于定义测试用例。
import { sum } from './sum'
: 这行代码从当前目录下的sum.js
文件中导入了sum
函数,以便在测试中使用。
test('adds 1 + 2 to equal 3', () => { ... })
: 这是一个测试用例,使用test
函数定义。第一个参数是测试用例的描述,第二个参数是一个函数,包含了测试用例的具体实现。
expect(sum(1, 2)).toBe(3)
: 在测试用例的实现中,调用了sum
函数,并使用expect
函数对其返回值进行断言。这里断言的意思是调用sum(1, 2)
的结果应该等于3
。
运行vitest查看测试用例是否通过
vitest常用指令
Vitest 的断言方法大致可以分为以下几类:
-
基本类型比较:
toBe
和not.toBe
: 检查值是否相等或不等。toBeDefined
和toBeUndefined
: 检查值是否定义或未定义。toBeNull
和toBeTruthy
/toBeFalsy
: 检查值是否为 null、零、空字符串等。
-
值的精确匹配:
toEqual
: 检查值的精确结构和内容(包括数组和对象)。toBeCloseTo
: 检查数值的近似相等。
-
类型和实例检查:
toBeInstanceOf
: 检查值是否是某个构造函数的实例。
-
正则表达式匹配:
toMatch
: 检查值是否匹配给定的正则表达式。
-
异常处理:
toThrow
: 检查函数是否抛出预期的错误。toThrowErrorMatchingSnapshot
: 检查错误是否与预期的错误信息一致。
-
自定义断言:
expect.extend
: 用户可以扩展自定义的断言方法。expect.addType
: 添加类型检查功能,如检查值是否为特定类型。
这些断言方法是 Vitest 测试框架中的核心工具,用于验证代码的行为是否符合预期。
详细的
expect(value).toBe(expected)
: 检查 value 是否等于 expected。expect(value).not.toBe(expected)
: 检查 value 是否不等于 expected。expect(value).toBeDefined()
: 检查 value 是否已定义。expect(value).toBeUndefined()
: 检查 value 是否未定义。expect(value).toBeNull()
: 检查 value 是否为 null。expect(value).toBeTruthy()
: 检查 value 是否为真值(非空字符串、非零数字、非false
、非null
、非undefined
)。expect(value).toBeFalsy()
: 检查 value 是否为假值(空字符串、零、false
、null
、undefined
)。expect(value).toEqual(expected)
: 检查 value 是否与 expected 相等,包括对象、数组等结构。expect(value).toBeCloseTo(expected, delta)
: 检查 value 是否与 expected 数值类型相差不超过 delta 的绝对值。expect(value).toBeInstanceOf(constructor)
: 检查 value 是否为 constructor 的实例。expect(value).toMatch(pattern)
: 检查 value 是否与 pattern 正则表达式匹配。expect(value).toThrow(error)
: 检查 value 是否是一个抛出 error 的函数。expect(value).toThrowErrorMatchingSnapshot()
: 检查 value 是否是一个抛出错误,并与快照进行比较。