熬夜写了Vite项目全流程从零搭建完整教程
使用 Vite 创建 Vue 2 项目完整步骤:
一、创建 Vite 项目
初始化项目
pnpm create vite@latest
# 选择 "Vanilla" 模板
# 项目名称输入 `vue2-vite-demo`
.../19726d6e7d7-8468 | +1 +
.../19726d6e7d7-8468 | Progress: resolved 1, reused 0, downloaded 1, added 1, done
|
o Project name:
| vue2-vite-demo
|
o Select a framework:
| Vanilla
|
o Select a variant:
| JavaScript
|
o Scaffolding project in E:\github\tpl\vue2-vite-demo...
|
— Done. Now run:
cd vue2-vite-demo
pnpm install
pnpm run dev
统一编辑器配置
根目录新建 .editorconfig
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false
安装 Vue 2 依赖
cd vue2-vite-demo
pnpm install -D @vitejs/plugin-vue2 vue-template-compiler
pnpm install vue@2
配置 Vite 在项目根目录创建
vite.config.js
:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
export default defineConfig({
plugins: [vue()]
})
修改项目结构
创建 src 目录,并将 main.js 移动到 src 目录。修改 index.html 文件,更新 main.js 的路径:
<script type="module" src="/src/main.js"></script>
创建 src/App.vue 文件,并添加以下内容:
修改 src/main.js 文件:
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App)
}).$mount('#app')
运行项目
配置完成后,可以运行以下命令启动项目:
pnpm run dev
二、集成 ESLint
不用版本的eslint引用的规则文件有差异,下面使用指定版本
初始化 ESLint 配置
pnpm install -D eslint@8.57.1 eslint-plugin-vue@9.17.0 @rushstack/eslint-patch@1.3.3
加配置文件 .eslintrc.cjs
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");
// @rushstack/eslint-patch 是由微软 Rush Stack 团队开发的工具,
// 主要用于 修复 ESLint 在现代 JavaScript/TypeScript 项目中的兼容性问题
// 尤其在复杂工具链或特定框架(如 Vue、React)中表现突出
module.exports = {
root: true,
extends: [
"eslint:recommended",
"plugin:vue/vue3-recommended", // 更全面的 Vue 规则(适用于 Vue 3)
],
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
modules: true
}
},
rules: {
}
};
添加忽略文件
.eslintignore
/node_modules/
/dist/
*.html
/public/
/build/
*.test.js
增加pnpm命令
"lint": "eslint src/ --ext .js,.ts,.vue",
"lint:fix": "eslint . --ext .js,.ts,.vue --fix"
修改main.js
import Vue from "vue";
import App from "./App.vue";
const a = 1;
new Vue({
render: (h) => h(App),
}).$mount("#app");
pnpm run lint
23:13:48 [vite] vite.config.js changed, restarting server...
23:13:48 [vite] server restarted.
E:\github\tpl\vue2-vite-demo\src\main.js
3:7 error 'a' is assigned a value but never used no-unused-vars
✖ 1 problem (1 error, 0 warnings)
控制台报错提示则配置成功
vite项目集成
pnpm i vite-plugin-eslint
修改vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue2";
import eslintPlugin from "vite-plugin-eslint";
export default defineConfig({
plugins: [
vue(),
eslintPlugin({
failOnError: false, //报错不影响编译
failOnWarning: false, // 警告不影响编译
include: ["src/**/*.js", "src/**/*.vue"],
}),
],
lintOnSave: true,
});
pnpm run dev
VITE v6.3.5 ready in 680 ms
➜ Local: http://localhost:5173
➜ Network: use --host to expose
➜ press h + enter to show help
16:02:47 [vite] (client) page reload src/main.js
16:02:48 [vite] (client) page reload src/main.js (x2)
E:\github\tpl\vue2-vite-demo\src\main.js
4:7 error 'a' is assigned a value but never used no-unused-vars
✖ 1 problem (1 error, 0 warnings)
16:02:48 [vite] (client) page reload src/main.js
三、增强开发体验
代码格式化(Prettier)
pnpm install -D prettier eslint-config-prettier @vue/eslint-config-prettier@9.0.0
#js项目替换这个包 @vue/eslint-config-prettier@9.0.0
pnpm install -D eslint-plugin-prettier
创建 .prettierrc.json
:
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": true,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}
修改 .eslintrc.js
:
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution');
// @rushstack/eslint-patch 是由微软 Rush Stack 团队开发的工具,
// 主要用于 修复 ESLint 在现代 JavaScript/TypeScript 项目中的兼容性问题
// 尤其在复杂工具链或特定框架(如 Vue、React)中表现突出
// 继承的位置后面的会覆盖前面的
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended', // 更全面的 Vue 规则(适用于 Vue 3)
'@vue/eslint-config-prettier', // vue中使用关闭冲突规则
'@vue/eslint-config-prettier/skip-formatting'// 跳过eslint格式化,把格式化交给prittier
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: {
modules: true
}
},
rules: {
'prettier/prettier': 'error'// 启用 Prettier 规则
}
};
增加pnpm命令
"format": "prettier --write src/"
VSCode 配置 安装插件:
ESLint
Prettier - Code Formatter
在 .vscode/settings.json
中添加:
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
Git 提交时自动格式化
pnpm install -D husky lint-staged
#先初始化仓库,有则跳过
git init
#9.x版本
npx husky-init
#8.x
npx husky install
$ npx husky-init
husky-init updating package.json
"husky install" command already exists in prepare script, skipping.
husky - Git hooks installed
husky - created .husky/pre-commit
please review changes in package.json
作用: 创建 .husky/ 目录 自动生成 prepare 脚本(自动执行 husky install)
修改 package.json
:
{
"scripts": {
"prepare": "husky install"
},
"lint-staged": {
"src/**/*.{js,vue}": [
"prettier --write",
"eslint"
]
}
}
修改 .husky/pro-commit :
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
pnpm run test
git add .
git commit 'xxxx'
```bash
✔ Preparing lint-staged...
⚠ Running tasks for staged files...
❯ package.json — 15 files
❯ src/**/*.{js,vue} — 2 files
✖ eslint [FAILED]
◼ prettier --write
◼ git add
✔ Applying modifications from tasks...
✖ eslint:
E:\github\tpl\vue2-vite-demo\src\main.js
3:7 error 'a' is assigned a value but never used no-unused-vars
✖ 1 problem (1 error, 0 warnings)
husky - pre-commit hook exited with code 1 (error)
```
四、自动化测试
vite项目集成vitest
pnpm install -D vitest
#dom操作 暂不需要
pnpm install -D jsdom
#vue挂载 暂不需要
pnpm install -D @vue/test-utils
编写测试
例如,我们将编写一个简单的测试来验证将两个数字相加的函数的输出。
utils/sum.js
js
export function sum(a, b) {
return a + b
}
test/utils/sum.test.js
js
import { expect, test } from 'vitest'
import { sum } from './sum.js'
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3)
})
TIP
一般情况下,执行测试的文件名中必须包含 ".test." 或 ".spec." 。
接下来,为了执行测试,请将以下部分添加到你的 package.json
文件中:
package.json
json
{
"scripts": {
"test": "vitest --run",
"test:watch": "vitest"
}
}
最后,运行yarn test
或 pnpm test
,具体取决于你的包管理器,Vitest 将打印此消息:
txt
✓ sum.test.js (1)
✓ adds 1 + 2 to equal 3
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 02:15:44
Duration 311ms
配置更多测试信息
vitest.config.js
import { mergeConfig, defineConfig } from 'vitest/config';
import viteConfig from './vite.config';
export default mergeConfig(
viteConfig,
defineConfig({
test: {}
})
);
五、集成github action
https://docs.github.com/zh/actions/about-github-actions/understanding-github-actions
新建空文件 package-lock.json
github action 会检测lock文件,默认没有检测pnpm-lock,用pnpm没有生成,需要手动创建
修改构建配置
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue2';
import eslintPlugin from 'vite-plugin-eslint';
export default defineConfig({
base: '/vue2-vite-demo', //跟仓库名一致
plugins: [
vue(),
eslintPlugin({
failOnError: false, //报错不影响编译
failOnWarning: false, // 警告不影响编译
include: ['src/**/*.js', 'src/**/*.vue']
})
],
lintOnSave: true
});
在根目录下增加文件
.github\workflows\deploy.yml
vite项目简单部署,使用pnpm
# 一个简单的 GitHub Pages 部署工作流
name: Deploy static content to Pages
on:
# 仅在推送到默认分支时运行
push:
branches: ['gh-pages']
# 这个选项可以使你手动在 Action tab 页面触发工作流
workflow_dispatch:
# 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# 允许一个并发部署
concurrency:
group: 'pages'
cancel-in-progress: true
jobs:
# 单次部署的工作描述
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Install dependencies
run: pnpm i
- name: Build
run: pnpm run build
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# 上传 dist 文件夹
path: './dist'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
创建github仓库
git remote add
#先推master,建立默认分支
git push --set-upstream origin master
修改github pages ,改成github actions
git branch -M gh-pages
git push --set-upstream origin gh-pages
提交后可以看到仓库工作流
这样就可以在github上部署自己的项目demo
https://cnlhb.github.io/vue2-vite-demo/
六、集成Commitlint
1. 核心定义
Commitlint 是基于 Node.js 的静态检查工具,通过解析 Git 提交消息的 commit-msg
钩子,验证其是否符合预设的格式规范(如 Conventional Commits)。它通过规则集(如提交类型、作用范围、主题格式等)约束开发者,避免提交信息混乱
2. 核心功能
规则检查 支持自定义规则集,例如:
类型(Type):强制使用
feat
(新功能)、fix
(修复)、docs
(网页变更)等预定义类型作用范围(Scope):限制提交影响的范围(如模块名),并强制小写或特定格式
主题(Subject):要求简洁描述(不超过 72 字符),禁止空值或句号结尾
正文(Body)与脚注(Footer):强制空行分隔,限制行长度
。
自动化集成 与 Husky、Git Hooks 结合,在提交时自动触发检查。若不符合规则,提交会被拦截并提示错误
多语言/框架支持 适用于 JavaScript、TypeScript、React、Vue 等项目,兼容主流开发场景
pnpm add -D @commitlint/cli @commitlint/config-conventional
添加文件
.commitlintrc.js
js
module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'chore']], // 限制提交类型 'scope-case': [2, 'always', 'lower-case'], // 作用范围强制小写 'subject-max-length': [2, 'always', 72] // 主题最大长度 } };
npx husky add .husky/commit-msg 'npx commitlint --edit "$1"'
这样提交就有格式检查
$ git cm 提交检查 → No staged files match any configured task. > vue2-vite-demo@0.0.0 test E:\github\tpl\vue2-vite-demo > vitest --run RUN v3.1.4 E:/github/tpl/vue2-vite-demo ✓ test/utils/sum.test.js (1 test) 2ms ✓ adds 1 + 2 to equal 3 1ms Test Files 1 passed (1) Tests 1 passed (1) Start at 13:47:11 Duration 1.58s (transform 796ms, setup 0ms, collect 796ms, tests 2ms, environment 0ms, prepare 106ms) ⧗ input: 提交检查 ✖ subject may not be empty [subject-empty] ✖ type may not be empty [type-empty] ✖ found 2 problems, 0 warnings ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint husky - commit-msg hook exited with code 1 (error)
3.高级用法,交互式提交
安装commitizen
安装自动化提示工具
pnpm i commitizen cz-conventional-changelog -D
package.json 中添加 cz指令, 执行
git-cz
指令"scripts": { "cz": "git-cz", }, "config": { "commitizen": { "path": "cz-conventional-changelog" } }
就可以在命令行中选择需要提交类型
安装可自定义的cz适配器
因为commitizen只支持英文,如果我想要支持中文指令和emoji,那么就必须安装可自定义的cz适配器了
pnpm i -D commitlint-config-cz cz-customizable
新增文件.cz-config.js
module.exports = { types: [ { value: ':sparkles: feat', name: '✨ feat: 新功能' }, { value: ':bug: fix', name: '🐛 fix: 修复bug' }, { value: ':package: build', name: '📦️ build: 打包' }, { value: ':zap: perf', name: '⚡️ perf: 性能优化' }, { value: ':tada: release', name: '🎉 release: 发布正式版' }, { value: ':lipstick: style', name: '💄 style: 代码的样式美化' }, { value: ':recycle: refactor', name: '♻️ refactor: 重构' }, { value: ':pencil2: docs', name: '✏️ docs: 文档变更' }, { value: ':white_check_mark: test', name: '✅ test: 测试' }, { value: ':rewind: revert', name: '⏪️ revert: 回退' }, { value: ':rocket: chore', name: '🚀 chore: 构建/工程依赖/工具' }, { value: ':construction_worker: ci', name: '👷 ci: CI related changes' } ], messages: { type: '请选择提交类型(必填)', customScope: '请输入文件修改范围(可选)', subject: '请简要描述提交(必填)', body: '请输入详细描述(可选)', breaking: '列出任何BREAKING CHANGES(可选)', footer: '请输入要关闭的issue(可选)', confirmCommit: '确定提交此说明吗?' }, allowCustomScopes: true, // 跳过问题 'body', 'footer' skipQuestions: ['body'], subjectLimit: 72 };
安装git-commit-emoji
pnpm i -D commitlint-config-git-commit-emoji
更新
commitlint.config.js
移除extends中原来的
@commitlint/config-conventional
,加入'git-commit-emoji', 'cz'
module.exports = { //extends: ['@commitlint/config-conventional'], //默认 extends: ['git-commit-emoji', 'cz'], rules: { // 'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'chore']], // 限制提交类型 'scope-case': [2, 'always', 'lower-case'], // 作用范围强制小写 'subject-max-length': [2, 'always', 72] // 主题最大长度 } };
更新
package.json
"cz": "cz-customizable", "config": { "commitizen": { "path": "node_modules/cz-customizable" }, "cz-customizable": { "config": "./.cz-config.cjs" } }
pnpm run cz > vue2-vite-demo@0.0.0 cz E:\github\tpl\vue2-vite-demo > cz-customizable cz-customizable standalone version >>> Using cz-customizable config specified in your package.json: E:\github\tpl\vue2-vite-demo\.cz-config.cjs All lines except first will be wrapped after 100 characters. ? 请选择提交类型(必填) ✨ feat: 新功能 ? 请输入文件修改范围(可选) project ? 请简要描述提交(必填) 增加中文交互式提交 ? 请输入要关闭的issue(可选) ###--------------------------------------------------------### :sparkles: feat(project): 增加中文交互式提交 ###--------------------------------------------------------### ? 确定提交此说明吗? Yes → No staged files match any configured task.
自动生成git commit 提交记录
pnpm install conventional-changelog conventional-changelog-cli -D
增加script命令
-p 指定风格* -i CHANGELOG.md 指定输出的文件名称 -s 输出到infile,这样就不需要指定与outfile相同的文件 -r 从最新的版本生成多少个版本。如果为0,则整个更改日志将被重新生成,输出文件将被覆盖。默认值:1 -n ./changelog-option.js 指定自定义配置
"changelog": "conventional-changelog -i CHANGELOG.md -s -r 0"
七、构建库模式
默认build,构建库模式,
build:demo 模式下,则构建体验demo
库模式下,不会把html打包进构建目录,则需要额外构建体验demo
可以根据自己的需求构建更多场景~
#统一设置环境变量命令,并修改打包文件夹 --outDir demo pnpm i cross-env -D
更新
package.json
"scripts": { "build:demo": "cross-env CUSTOM_NODE_ENV=demo vite build --outDir demo" }, "files": [ "dist" ], "main": "./dist/index.umd.cjs", "module": "./dist/index.js", "exports": { ".": { "import": "./dist/index.js", "require": "./dist/index.umd.cjs" }, "./style.css": "./dist/style.css" },
新建 src/index.js
import App from './App.vue'; export default App;
修改 vite.config.js
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue2'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import eslintPlugin from 'vite-plugin-eslint'; const __dirname = dirname(fileURLToPath(import.meta.url)); let libConfig = { build: { lib: { entry: resolve(__dirname, 'src/index.js'), name: 'index', // 将添加适当的扩展名后缀 fileName: 'index' }, rollupOptions: { // 确保外部化处理那些 // 你不想打包进库的依赖 external: ['vue'], output: { // 在 UMD 构建模式下为这些外部化的依赖 // 提供一个全局变量 globals: { vue: 'Vue' } } } } }; if (process.env.CUSTOM_NODE_ENV === 'demo') { libConfig = { build: {} }; } export default defineConfig({ base: '/vue2-vite-demo', plugins: [ vue(), eslintPlugin({ failOnError: false, //报错不影响编译 failOnWarning: false, // 警告不影响编译 include: ['src/**/*.js', 'src/**/*.vue'] }) ], build: { ...libConfig.build }, resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, lintOnSave: true });
更改github deploy.yml
- name: Build run: pnpm run build:demo - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: # 上传 demo文件夹 path: './demo' - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4
npm run build > vue2-vite-demo@0.0.0 build > vite build vite v6.3.5 building for production... ✓ 3 modules transformed. dist/index.js 0.51 kB │ gzip: 0.32 kB dist/index.umd.cjs 0.57 kB │ gzip: 0.35 kB ✓ built in 1.25s npm run build:demo > vue2-vite-demo@0.0.0 build:demo > cross-env CUSTOM_NODE_ENV=demo vite build --outDir demo vite v6.3.5 building for production... ✓ 7 modules transformed. demo/index.html 0.48 kB │ gzip: 0.30 kB demo/assets/index-CrYBktwj.css 1.20 kB │ gzip: 0.62 kB demo/assets/index-CpDs40Uh.js 71.80 kB │ gzip: 26.38 kB ✓ built in 1.49s
八、验证配置
手动检查代码
pnpm run lint
格式化
pnpm run format
测试
pnpm run test
提交
git add . pnpm run cz
日志生成
pnpm run changelog
构建
pnpm run build pnpm run build:demo
关键依赖版本
包名
使用版本
eslint
8.x
eslint-plugin-vue
9.x
@vitejs/plugin-vue2
2.3.1
prettier
3.x
husky
8..0.0
包名
使用版本
eslint
8.x
eslint-plugin-vue
9.x
@vitejs/plugin-vue2
2.3.1
prettier
3.x
husky
8..0.0
完整依赖文件
{ "name": "vue2-vite-demo", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vite build", "build:demo": "cross-env CUSTOM_NODE_ENV=demo vite build --outDir demo", "preview": "vite preview", "lint": "eslint src/ --ext .js,.ts,.vue", "lint:fix": "eslint . --ext .js,.ts,.vue --fix", "format": "prettier --write src/", "prepare": "husky install", "test": "vitest --run", "test:watch": "vitest", "cz": "cz-customizable", "changelog": "conventional-changelog -i CHANGELOG.md -s -r 0" }, "devDependencies": { "@commitlint/cli": "^19.8.1", "@commitlint/config-conventional": "^19.8.1", "@rushstack/eslint-patch": "1.3.3", "@vitejs/plugin-vue2": "^2.3.3", "@vue/eslint-config-prettier": "^9.0.0", "commitizen": "^4.3.1", "commitlint-config-cz": "^0.13.3", "commitlint-config-git-commit-emoji": "^1.0.0", "conventional-changelog": "^7.0.2", "conventional-changelog-cli": "^5.0.0", "cross-env": "^7.0.3", "cz-conventional-changelog": "^3.3.0", "cz-customizable": "^7.4.0", "eslint": "8.57.1", "eslint-config-prettier": "^10.1.5", "eslint-plugin-vue": "9.17.0", "husky": "^8.0.0", "lint-staged": "^16.1.0", "prettier": "^3.5.3", "vite": "^6.3.5", "vite-plugin-eslint": "^1.8.1", "vitest": "^3.1.4", "vue-template-compiler": "^2.7.16" }, "dependencies": { "vue": "2.7.16" }, "lint-staged": { "src/**/*.{js,vue}": [ "prettier --write", "eslint" ] }, "config": { "commitizen": { "path": "node_modules/cz-customizable" }, "cz-customizable": { "config": "./.cz-config.cjs" } } }
总结
整个教程耗时两天时间,从搭建到编写文档,再到文档搭建项目,优化文档,确实耗时间,但也理清了各个流程,也算是有一定的收获,希望这个教程也帮到您。
继续加油,前端之路越走越稳!🚀
by aiwa