选择pnpm主要原因:编译速度pnpm
>> yarn
>> npm
。
npm install pnpm -g
win11系统,pnpm build 的时候遇到了问题
set-ExecutionPolicy RemoteSigned
解决。如果早一些的版本需要管理员身份运行。
## 增加包
npm install
pnpm add
## 卸载包
npm uninstall
pnpm remove
## 运行项目
npm run dev
pnpm dev
## 打包项目
npm run build
pnpm build
#查看
pnpm get registry
#临时
pnpm --registry https://registry.npmmirror.com install axios
#永久
pnpm config set registry https://registry.npmmirror.com
## 创建项目,根据提示步骤进行
pnpm create vite
## 运行项目
pnpm dev
## 生产打包
pnpm build
复制package.json
保留想要用的安装包,pnpm install
即可全部安装。
scripts
部分根据需要保留对应指令。commitizen
和lint-staged
不用可以删除。- 格式化等去查看对应部分,增加相应的配置。
{
"name": "vue3-collection",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"prettier:comment": "自动格式化当前目录下的所有文件",
"prettier": "prettier --write",
"eslint:comment": "使用 ESLint 检查并自动修复 src 目录下所有扩展名为 .js 和 .vue 的文件",
"eslint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src",
"commit:comment": "引导设置规范化的提交信息",
"commit": "git-cz",
"prepare": "husky install"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-customizable"
}
},
"lint-staged": {
"*.{js,ts}": [
"pnpm eslint",
"pnpm prettier"
]
},
"dependencies": {
"ant-design-vue": "^4.0.7",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.0",
"vue": "^3.3.8",
"vue-router": "^4.2.5"
},
"devDependencies": {
"vite-plugin-compression": "^0.5.1",
"@commitlint/cli": "^18.4.3",
"@commitlint/config-conventional": "^18.4.3",
"@vitejs/plugin-vue": "^4.5.0",
"commitizen": "^4.3.0",
"commitlint-config-cz": "^0.13.3",
"cz-conventional-changelog": "^3.3.0",
"cz-customizable": "^7.0.0",
"eslint": "^8.55.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-vue": "^9.19.2",
"husky": "^8.0.3",
"lint-staged": "^15.2.0",
"mockjs": "^1.1.0",
"prettier": "^3.1.0",
"sass": "^1.69.5",
"terser": "^5.26.0",
"vite": "^5.0.7",
"vite-plugin-imagemin": "^0.6.1",
"vite-plugin-mock": "^2.9.6"
}
}
pinia官网:pinia.web3doc.top/
pnpm i pinia --save
pnpm i vue-router --save
#函数包
pnpm i @vueuse/core
#持久化
pnpm i pinia-plugin-persistedstate --save
import { createPinia } from 'pinia'
import router from './router/index'
app.use(createPinia()).use(router)
import { defineStore } from "pinia";
// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore("main", {
state: () => {
return {
count: 0,
};
},
getters: {},
actions: {
increment() {
this.count++;
},
},
//数据默认是存在localStorage
persist: {
enabled: true, //开启
storage:sessionStorage, //修改存储位置
key:'userInfo', //设置存储的key
paths: ['id'],//指定要长久化的字段
},
});
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/login',
name: 'Login',
meta: {
title: '登录',
keepAlive: true,
requireAuth: false
},
component: () => import('@/pages/login.vue')
},
{
path: '/',
redirect: '/login'
}
]
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
这时候store
不同于vuex
,他是一个ref
变量,在标签里直接使用{{store.xx}}
<template>
<div>{{store.count}}div>
<button @click="go('/login')">go linkbutton>
template>
<script setup>
import { useStore } from '@/store/index'
import { storeToRefs } from 'pinia';
import {useRouter} from 'vue-router'
const store = useStore();
const router = useRouter();
//不能解构而是用storeToRefs保持响应性
const {count} = storeToRefs(store)
//更新
store.increment();
function go(path){
router.push({path:path})
}
script>
## 安装
pnpm i eslint eslint-plugin-vue --save-dev
pnpm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev
semi
设置0,关闭了对逗号检查comma-dangle
设置0,关闭了分号检查space-before-function-paren
设置0,关闭了方法名括号前空格检查vue/html-self-closing
,html
-void
改为always
规避img
等单标签报错parser: 'babel-eslint'
解决了缺包提示parser: 'vue-eslint-parser'
,编译es6等不出错// 'off' or 0 - 关闭这个规则校验
// 'warn' or 1 - 开启这个规则校验,但只是提醒,不会退出
// 'error' or 2 - 开启这个规则校验,并退出
module.exports = {
root: true,
parserOptions: {
ecmaVersion: 7,
ecmaFeatures: {
jsx: true,
modules: true,
},
},
parser: 'vue-eslint-parser',
env: {
es6: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended',
'prettier',
'plugin:prettier/recommended',
],
plugins: ['vue'],
globals: {
document: false,
navigator: false,
window: false,
},
rules: {
'accessor-pairs': 2,
'arrow-spacing': [
2,
{
before: true,
after: true,
},
],
'block-spacing': [2, 'always'],
'comma-dangle': [0, 'never'],
'comma-spacing': [
2,
{
before: false,
after: true,
},
],
'comma-style': [2, 'last'],
'constructor-super': 2,
curly: [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
eqeqeq: [2, 'allow-null'],
'generator-star-spacing': [
2,
{
before: true,
after: true,
},
],
'handle-callback-err': [2, '^(err|error)$'],
indent: [
2,
2,
{
SwitchCase: 1,
},
],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [
2,
{
beforeColon: false,
afterColon: true,
},
],
'keyword-spacing': [
2,
{
before: true,
after: true,
},
],
'new-cap': [
2,
{
newIsCap: true,
capIsNew: false,
},
],
'new-parens': 2,
'no-array-constructor': 2,
'no-console': 0,
'no-caller': 2,
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 2,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [
2,
{
allowLoop: false,
allowSwitch: false,
},
],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [
2,
{
max: 1,
},
],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 0,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [
2,
{
defaultAssignment: false,
},
],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [
2,
{
vars: 'all',
args: 'none',
},
],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [
2,
{
initialized: 'never',
},
],
'operator-linebreak': [
2,
'after',
{
overrides: {
'?': 'before',
':': 'before',
},
},
],
'padded-blocks': [2, 'never'],
quotes: [
2,
'single',
{
avoidEscape: true,
allowTemplateLiterals: true,
},
],
semi: [0, 'never'],
'semi-spacing': [
2,
{
before: false,
after: true,
},
],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [0, 'always'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [
2,
{
words: true,
nonwords: false,
},
],
'spaced-comment': [
2,
'always',
{
markers: [
'global',
'globals',
'eslint',
'eslint-disable',
'*package',
'!',
',',
],
},
],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
yoda: [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [
2,
'always',
{
objectsInObjects: false,
},
],
'array-bracket-spacing': [2, 'never'],
'vue/jsx-uses-vars': 2,
'vue/max-attributes-per-line': [
'error',
{
singleline: 3,
multiline: {
max: 13,
},
},
],
'vue/html-self-closing': [
'error',
{
html: {
void: 'always',
normal: 'any',
component: 'always',
},
svg: 'always',
math: 'always',
},
],
},
};
如果遇到报错可对应增加!xx
解决配置类文件被检测报错的问题。
node_modules/
dist/
index.html
!.eslintrc.js
!.prettierrc.js
!.gitignore
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"trailingComma": "all",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "always",
"rangeStart": 0,
"rangeEnd": 9999999,
"requirePragma": false,
"insertPragma": false,
"proseWrap": "preserve",
"htmlWhitespaceSensitivity": "css",
"endOfLine": "auto"
}
#scss
pnpm add -D sass
全局变量
css: {
preprocessorOptions: {
scss: {
/** 如果引入多个文件,可以使用
* '@import "@/assets/scss/globalVariable1.scss";
* @import"@/assets/scss/globalVariable2.scss";'
**/
additionalData: '@import "@/style/var.scss";',
},
},
},
#安装 commitizen (交互式提交 + 自定义提示文案 + Commit规范)
pnpm install -D commitizen cz-conventional-changelog @commitlint/config-conventional @commitlint/cli commitlint-config-cz cz-customizable
package.json
scripts
添加,使用pnpm commit
命令替代git commit
scripts:{
"commit:comment": "引导设置规范化的提交信息",
"commit": "git-cz",
}
"config": {
"commitizen": {
"path": "./node_modules/cz-customizable"
}
},
types
为自定义内容,value
跟commitlint.config.js
对应
module.exports = {
types: [{
value: 'feature',
name: 'feature: 增加新功能'
},
{
value: 'bug',
name: 'bug: 测试反馈bug列表中的bug号'
},
{
value: 'fix',
name: 'fix: 修复bug'
},
{
value: 'ui',
name: 'ui: 更新UI'
},
{
value: 'docs',
name: 'docs: 文档变更'
},
{
value: 'style',
name: 'style: 代码格式(不影响代码运行的变动)'
},
{
value: 'perf',
name: 'perf: 性能优化'
},
{
value: 'refactor',
name: 'refactor: 重构(既不是增加feature,也不是修复bug)'
},
{
value: 'release',
name: 'release: 发布'
},
{
value: 'deploy',
name: 'deploy: 部署'
},
{
value: 'test',
name: 'test: 增加测试'
},
{
value: 'chore',
name: 'chore: 构建过程或辅助工具的变动(更改配置文件)'
},
{
value: 'revert',
name: 'revert: 回退'
},
{
value: 'build',
name: 'build: 打包'
}
],
// override the messages, defaults are as follows
messages: {
type: '请选择提交类型:',
customScope: '请输入您修改的范围(可选):',
subject: '请简要描述提交 message (必填):',
body: '请输入详细描述(可选,待优化去除,跳过即可):',
footer: '请输入要关闭的issue(待优化去除,跳过即可):',
confirmCommit: '确认使用以上信息提交?(y/n/e/h)'
},
allowCustomScopes: true,
skipQuestions: ['body', 'footer'],
subjectLimit: 72
};
module.exports = {
extends: ['@commitlint/config-conventional', 'cz'],
rules: {
'type-enum': [
2,
'always',
[
'feature', // 新功能(feature)
'bug', // 此项特别针对bug号,用于向测试反馈bug列表的bug修改情况
'fix', // 修补bug
'ui', // 更新 ui
'docs', // 文档(documentation)
'style', // 格式(不影响代码运行的变动)
'perf', // 性能优化
'release', // 发布
'deploy', // 部署
'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动)
'test', // 增加测试
'chore', // 构建过程或辅助工具的变动
'revert', // feat(pencil): add ‘graphiteWidth’ option (撤销之前的commit)
'merge', // 合并分支, 例如: merge(前端页面): feature-xxxx修改线程地址
'build', // 打包
],
],
// 格式 小写
'type-case': [2, 'always', 'lower-case'],
// 不能为空
'type-empty': [2, 'never'],
// 范围不能为空
'scope-empty': [2, 'never'],
// 范围格式
'scope-case': [0],
// 主要 message 不能为空
'subject-empty': [2, 'never'],
// 以什么为结束标志,禁用
'subject-full-stop': [0, 'never'],
// 格式,禁用
'subject-case': [0, 'never'],
// 以空行开头
'body-leading-blank': [1, 'always'],
'header-max-length': [0, 'always', 72],
},
};
根据步骤完成前 5 步的设置,git提交代码commit时就会先执行husky进行检查。检查通过方可提交。
# 1.安装
pnpm i husky lint-staged -D
# 2.生成 .husky 的文件夹
npx husky install
# 3.添加 hooks,会在 .husky 目录下生成一个 pre-commit 脚本文件
npx husky add .husky/pre-commit "npx --no-install lint-staged"
# 4.添加 commit-msg
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
# 5.package.json中添加以下配置
"lint-staged": {
"*.{js,ts}": [
"pnpm eslint",
"pnpm prettier"
]
}
# 6.提交代码 `git commit -m "message"` 就会看到 hook 生效了。
vite官网中mock相关配置:vite-plugin-mock
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
// import { visualizer } from 'rollup-plugin-visualizer';
import viteCompression from 'vite-plugin-compression';
import viteImagemin from 'vite-plugin-imagemin';
import { viteMockServe } from 'vite-plugin-mock';
import path from 'path';
// https://vitejs.dev/config/
export default defineConfig({
base: './',//解决刷新404问题
resolve: {
alias: { '@': path.resolve('src') },//根路径
extensions: ['.mjs', '.mts', '.js', '.tsx', '.jsx', '.json'],//可省略后缀的文件
},
plugins: [
vue(),
//mock数据:injectCode在生产环境启用的话需要。
viteMockServe({
mockPath:'./mock',
localEnabled: true,
prodEnabled: false,
// injectCode: `import {mockServer} from 'mockServer';mockServer()`,
}),
//代码压缩
viteCompression({ threshold: 10240, algorithm: 'gzip' }),
//图片压缩
viteImagemin({
gifsicle: {
optimizationLevel: 7,
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
mozjpeg: {
quality: 20,
},
pngquant: {
quality: [0.8, 0.9],
speed: 4,
},
svgo: {
plugins: [
{
name: 'removeViewBox',
},
{
name: 'removeEmptyAttrs',
active: false,
},
],
},
}),
],
// 全局变量设置
css: {
preprocessorOptions: {
scss: {
/** 如果引入多个文件,可以使用
* '@import "@/assets/scss/globalVariable1.scss";
* @import"@/assets/scss/globalVariable2.scss";'
**/
additionalData: '@import "@/style/var.scss";',
},
},
},
build: {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
// 让每个插件都打包成独立的文件
return id
.toString()
.split('node_modules/')[1]
.split('/')[0]
.toString();
}
},
},
},
},
server: {
host: '0.0.0.0', // ip
port: 5001, // 端口号
open: false, // 是否自动在浏览器打开
https: false, // 是否开启 https
// 跨域代理配置
proxy: {
'/api': {
target: 'http:192.168.1.100:9094',
changeOrigin: false,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});
mockServer.js
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
//mock在最外层根目录下
import routes from '../mock/index';
export function mockServer() {
createProdMockServer([...routes]);
}