pnpm create vite editor --template vue
/* vite.config.js */
import { defineConfig } from 'vite';
import { resolve } from 'path';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
base: './',
plugins: [
vue(),
],
resolve: {
alias: {
'@': resolve(__dirname, './src') ,
},
},
server: {
// 是否开启 https
https: false,
// 端口号
port: 3000,
// 监听所有地址
host: '0.0.0.0',
// 服务启动时是否自动打开浏览器
open: true,
// 允许跨域
cors: true,
// 自定义代理规则
proxy: {},
},
build: {
// 设置最终构建的浏览器兼容目标
target: 'es2015',
// 构建后是否生成 source map 文件
sourcemap: false,
// chunk 大小警告的限制(以 kbs 为单位)
chunkSizeWarningLimit: 2000,
// 启用/禁用 gzip 压缩大小报告
reportCompressedSize: false,
},
});
├── dist/
└── src/
├── api/ // 接口请求目录
├── assets/ // 静态资源目录
├── common/ // 通用类库目录
├── components/ // 公共组件目录
├── router/ // 路由配置目录
├── store/ // 状态管理目录
├── style/ // 通用样式目录
├── utils/ // 工具函数目录
├── views/ // 页面组件目录
├── App.vue
├── main.js
├── tests/ // 单元测试目录
├── index.html
├── jsconfig.json // JavaScript 配置文件
├── vite.config.js // Vite 配置文件
└── package.json
└── pnpm-workspace.yaml // 工作空间
创建 pnpm-workspace.yaml
packages:
- 'src/*'
pnpm add vue-router -w
└── src/
├── router/
├── index.js
├── modules/ // 各路由模块目录
├── index.js // 集成导出各路由模块
├── test.js
├── ...
/* src/router/index.js */
import { createRouter, createWebHistory } from "vue-router";
import modules from './modules';
const routes = [...modules];
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
scrollBehavior(){
return {
el: '#app',
top: 0,
behavior: 'smooth',
};
},
});
export default router;
/* src/main.js */
import router from './router';
const app = createApp(App);
app.use(router);
pnpm add pinia -w
/* src/store/modules/test.js */
import { defineStore } from 'pinia';
/**
* import { useStore } from '@/store'
* const store = useStore()
* 重置store:store.$reset()
* sotre.$patch({}) / store.$patch((state) => {})
*
*/
export const useTestStore = defineStore('test', {
state: () => ({}),
// getters 可以用来进行一些计算的操作
getters: {
},
// 没有 mutation
// 没有 modules
// actions 可以是同步也可以是异步
// actions 异步调用接口,处理响应结果
actions: {
test(){
// 执行一些操作
}
}
});
// 扁平化,不再使用 modules
export const useToDoStore = defineStore('todo', {});
<script setup>
import { useTestStore } from '@/store';
const testStore = useTestStore;
// 调用 test actions
testStore.test();
script>
└── src/
├── store/
├── index.js
├── modules/
├── index.js
├── test.js
├── ...
/* src/store/index.js */
import { createPinia } from "pinia";
const store = createPinia();
export default store;
export * from './modules';
/* src/main.js */
import store from './store';
const app = createApp(App);
app.use(store);
pnpm add element-plus -w
pnpm add -w -D unplugin-vue-components unplugin-auto-import
/* vite.config.ts */
import { defineConfig } from 'vite';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
export default defineConfig({
// ...
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
});
使用组件时不需要再导入。
<template>
<el-config-provider :size="size" :z-index="zIndex">
<router-view />
el-config-provider>
template>
<script setup>
const zIndex = ref(3000);
const size = ref('small');
script>
pnpm add axios -w
/* src/utils/request.js */
import axios from 'axios';
// 创建请求实例
const instance = axios.create({
baseURL: '/api',
// 指定请求超时的毫秒数
timeout: 1000,
// 表示跨域请求时是否需要使用凭证
withCredentials: false,
});
// 前置拦截器(发起请求之前的拦截)
instance.interceptors.request.use(
(config) => {
/**
* 在这里一般会携带前台的参数发送给后台,比如下面这段代码:
* const token = getToken()
* if (token) {
* config.headers.token = token
* }
*/
return config;
},
(error) => {
return Promise.reject(error);
},
);
// 后置拦截器(获取到响应时的拦截)
instance.interceptors.response.use(
(response) => {
/**
* 根据你的项目实际情况来对 response 和 error 做处理
* 这里对 response 和 error 不做任何处理,直接返回
*/
return response;
},
(error) => {
const { response } = error;
if (response && response.data) {
return Promise.reject(error);
}
const { message } = error;
console.error(message);
return Promise.reject(error);
},
);
vite 内置 less,仅需安装即可
pnpm add less -w -D
/* vite.config.js */
export default defineConfig({
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
additionalData: `@import "${resolve(__dirname, 'src/style/variables.less')}";`
}
}
}
// css: {
// preprocessorOptions: {
// less: {
// modifyVars: {
// hack: `true; @import (reference) "${resolve('src/style/variables.less')}";`,
// },
// math: 'strict',
// javascriptEnabled: true,
// },
// },
// },
});
创建 src/style/variables.less
EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs.
EditorConfig帮助跨不同编辑器和ide从事同一项目的多个开发人员维护一致的编码风格。
EditorConfig for VSCode
.editorconfig
): # .editorconfig
# 表示最顶层的 EditorConfig 配置文件
root = true
# 表示所有文件适用
[*]
# 缩进风格(space|tab|unset)
indent_style = space
# 控制换行类型(lf|cr|crlf|unset)
end_of_line = lf
# 设置文件字符集 utf-8
charset = utf-8
# 去除行首的任意空白字符
trim_trailing_whitespace = true
# 始终在文件末尾插入一个新行
insert_final_newline = true
# 表示 *.md 文件适用以下规则
[*.md]
max_line_length = off
trim_trailing_whitespace = false
# 表示仅 ts、js、vue、css 文件适用以下规则
[*.{ts,js,vue,css}]
indent_size = 4
ESLint 可组装的JavaScript和JSX检查工具
安装
ESLint
: ESLint 本体eslint-define-config
: 改善 ESLint 规范编写体验eslint-plugin-vue
: 适用于 Vue 文件的 ESLint 插件eslint-config-airbnb-base
: Airbnb JavaScript 风格指南eslint-plugin-import
: 使用 eslint-config-airbnb-base 时必须安装的前置插件vue-eslint-parser
: 使用 eslint-plugin-vue 时必须安装的 ESLint 解析器pnpm add -w eslint eslint-define-config eslint-config-airbnb-base eslint-plugin-import eslint-plugin-vue vue-eslint-parser -D
VSCode 安装插件 ESLint
配置( .eslintrc.js
)
/* .eslintrc.js */
const { defineConfig } = require('eslint-define-config');
module.exports = defineConfig({
root: true,
env: {
browser: true,
jest: true,
node: true,
es6: true
},
plugins: ['vue'],
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
allowImportExportEverywhere: true,
ecmaFeatures: {
jsx: true,
},
},
extends: [
'airbnb-base',
'eslint:recommended',
'plugin:vue/vue3-essential',
'plugin:vue/vue3-recommended',
// 解决 prettier 冲突
'plugin:prettier/recommended',
],
rules: {
// 禁止使用多余的包
'import/no-extraneous-dependencies': 0,
// 确保在导入路径内一致使用扩展名
'import/extensions': 0,
// 确保导入指向可以解析的文件/模块
'import/no-unresolved': 0,
// 首选默认导出导入/首选默认导出
'import/prefer-default-export': 0,
// 要求使用 let/const,而不是 var
'no-var': 'error',
// 禁止使用 new 以避免产生副作用
'no-new': 1,
// 禁止变量声明与外层作用域变量同名
'no-shadow': 0,
// 禁用 console
'no-console': 0,
// 禁止标识符中有悬空下划线
'no-underscore-dangle': 0,
// 禁止在可能与比较操作符相混淆的地方使用箭头函数
'no-confusing-arrow': 0,
// 禁用一元操作符 ++ 和 --
'no-plusplus': 0,
// 禁止对 function 参数进行重新赋值
'no-param-reassign': 0,
// 禁用特定的语法
'no-restricted-syntax': 0,
// 禁止在变量定义之前使用它们
'no-use-before-define': 0,
// 禁止直接调用 Object.prototypes 的内置属性
'no-prototype-builtins': 0,
// 禁止可以在有更简单的可替代的表达式时使用三元操作符
'no-unneeded-ternary': 'error',
// 禁止重复模块导入
'no-duplicate-imports': 'error',
// 禁止在对象中使用不必要的计算属性
'no-useless-computed-key': 'error',
// 强制使用一致的缩进(4个空格)
indent: ['error', 4],
// 强制使用驼峰式写法
camelcase: 0,
// 强制类方法使用 this
'class-methods-use-this': 0,
// 要求构造函数首字母大写
'new-cap': 0,
// 强制一致的使用 function 声明函数或表达式
'func-style': 0,
// 强制一行的最大长度
'max-len': 0,
// 要求 return 语句要么总是指定返回的值,要么不指定
'consistent-return': 0,
// 强制 switch 要有 default 分支
'default-case': 2,
// 强制剩余和扩展运算符及其表达式之间有空格
'rest-spread-spacing': 'error',
// 要求使用 const 声明那些声明后不再被修改的变量
'prefer-const': 'error',
// 强制箭头函数的箭头前后使用一致的空格
'arrow-spacing': 'error',
},
// overrides: [
// {
// file: ['*.vue'],
// rules: {
// // 要求组件名称总是多个单词
// 'vue/multi-word-component-names': 0,
// }
// }
// ]
});
prettier 是代码格式化工具
VSCode 安装插件 Prettier - Code formatter
安装:pnpm add -w prettier -D
配置( .prettierrc.js
)
/* .prettierrc.js */
module.exports = {
// 一行最多 120 个字符
printWidth: 120,
// 不用 tab,用空格
useTabs: false,
// 缩进4个空格
tabWidth: 4,
// 行尾要有分号
semi: true,
// 使用单引号
singleQuote: true,
// 对象的 key 仅在必要时用双引号
jsxSingleQuote: false,
// 末尾需要有逗号
trailingComma: 'all',
// 大括号内的首尾需要空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 箭头函数,只有一个参数的时候,也需要写括号
arrowParens: 'always',
// 每个文件格式化的范围是文件的全部内容
rangeStart: 0,
rangeEnd: Infinity,
// 不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准
proseWrap: 'preserve',
// 根据显示样式决定 html 要不要折行
htmlWhitespaceSensitivity: 'css',
// vue 文件中的 script 和 style 内不用缩进
vueIndentScriptAndStyle: false,
// 换行符使用 lf
endOfLine: 'lf',
// 格式化嵌入的内容
embeddedLanguageFormatting: 'auto',
// html, vue, jsx 中的每个属性占一行
singleAttributePerLine: false,
}
过滤( .prettierignore
)
## OS
.DS_Store
.idea
.editorconfig
pnpm-lock.yaml
.npmrc
# Ignored suffix
*.log
*.md
*.svg
*.png
*.ico
*ignore
## Local
.husky
## Built-files
.cache
dist
解决与 ESLint 冲突
pnpm add -w eslint-plugin-prettier eslint-config-prettier -D
安装:pnpm add -w -D stylelint stylelint-config-standard stylelint-config-prettier stylelint-config-recommended-vue
配置( .stylelintrc.js
)
module.exports = {
root: true,
defaultSeverity: 'error',
extends: [
'stylelint-config-standard',
'stylelint-config-prettier',
'stylelint-config-recommended-vue',
],
plugins: ['stylelint-order'],
rules: {
// 不允许未知函数
'function-no-unknown': null,
// 指定类选择器的模式
'selector-class-pattern': null,
// 禁止空源码
'no-empty-source': null,
// 指定字符串使用单引号
'string-quotes': 'single',
// 禁止未知的@规则
'at-rule-no-unknown': [
true,
{
ignoreAtRules: [
'tailwind',
'apply',
'variants',
'responsive',
'screen',
'function',
'if',
'each',
'include',
'mixin',
],
},
],
// 指定@规则名的大小写
'at-rule-name-case': 'lower',
// 指定缩进
indentation: [
2,
{
severity: 'warning',
},
],
// 禁止未知的伪类选择器
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global'],
},
],
// 禁止未知的伪元素选择器
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep'],
},
],
'order/properties-order': [
'position',
'top',
'right',
'bottom',
'left',
'z-index',
'display',
'justify-content',
'align-items',
'float',
'clear',
'overflow',
'overflow-x',
'overflow-y',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'width',
'min-width',
'max-width',
'height',
'min-height',
'max-height',
'font-size',
'font-family',
'font-weight',
'border',
'border-style',
'border-width',
'border-color',
'border-top',
'border-top-style',
'border-top-width',
'border-top-color',
'border-right',
'border-right-style',
'border-right-width',
'border-right-color',
'border-bottom',
'border-bottom-style',
'border-bottom-width',
'border-bottom-color',
'border-left',
'border-left-style',
'border-left-width',
'border-left-color',
'border-radius',
'text-align',
'text-justify',
'text-indent',
'text-overflow',
'text-decoration',
'white-space',
'color',
'background',
'background-position',
'background-repeat',
'background-size',
'background-color',
'background-clip',
'opacity',
'filter',
'list-style',
'outline',
'visibility',
'box-shadow',
'text-shadow',
'resize',
'transition',
],
},
overrides: [
{
files: ['*.vue', '**/*.vue', '*.html', '**/*.html'],
extends: ['stylelint-config-html'],
rules: {
// 指定关键帧名称的模式
'keyframes-name-pattern': null,
// 禁止未知的伪类选择器
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['deep', 'global'],
},
],
// 禁止未知的伪元素选择器
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'],
},
],
},
},
{
files: ['*.less', '**/*.less'],
customSyntax: 'postcss-less',
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
},
],
}
忽略检测( .stylelintignore
)
# .stylelintignore
# 旧的不需打包的样式库
*.min.css
# 其他类型文件
*.js
*.jpg
*.woff
# 测试和打包目录
/test/
/dist/*
/public/*
public/*
/node_modules/
VSCode 安装插件 Stylelint
You can use it to lint your commit messages, run tests, lint code, etc… when you commit or push. Husky supports all Git hooks.
您可以使用它来检测提交消息、运行测试、检测代码等。当你承诺或推动的时候。Husky支持所有Git钩子。
如果没有 npx 命令,执行
cnpm install -g npx
安装
安装(自动):pnpm dlx husky-init && pnpm install
lint-staged
只需要用 ESLint 修复此次写的代码,而不去影响其他的代码,此时需要借助 lint-staged 工具。
lint-staged 一般结合 husky 来使用,它可以让 husky 的 hook 触发的命令只作用于 git 暂存区的文件,而不会影响到其他文件。
安装:pnpm add -w lint-staged -D
配置( package.json
)
{
// "husky": {
// "hooks": {
// "pre-commit": "lint-staged",
// "commit-msg": "npx --no-install commitlint --edit $1"
// }
// },
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"prettier --write",
"eslint --fix"
],
"*.vue": [
"prettier --write",
"eslint --fix",
"stylelint --fix"
],
"*.{html,vue,vss,sass,less}": [
"prettier --write",
"stylelint --fix"
],
"package.json": [
"prettier --write"
],
"*.md": [
"prettier --write"
]
}
}
Hook(pre-commit)
npx husky add .husky/pre-commit 'npx lint-staged'
git-cz
规范提交
cnpm install -g git-cz commitizen
pnpm add -w git-cz -D
package.json
){
"config": {
"commitizen": {
"path": "git-cz"
}
}
}
package.json
){
"scripts": {
"commit": "git-cz"
}
}
changelog.config.js
)/* 修改提示 */
module.exports = {
disableEmoji: false,
format: '{type}{scope}: {emoji}{subject}',
list: ['test', 'feat', 'fix', 'chore', 'docs', 'refactor', 'style', 'ci', 'perf'],
maxMessageLength: 64,
minMessageLength: 3,
questions: ['type', 'scope', 'subject', 'body', 'breaking', 'issues', 'lerna'],
scopes: [],
types: {
chore: {
description: 'Build process or auxiliary tool changes',
emoji: '',
value: 'chore',
},
ci: {
description: 'CI related changes',
emoji: '',
value: 'ci',
},
docs: {
description: 'Documentation only changes',
emoji: '✏️',
value: 'docs',
},
feat: {
description: 'A new feature',
emoji: '',
value: 'feat',
},
fix: {
description: 'A bug fix',
emoji: '',
value: 'fix',
},
perf: {
description: 'A code change that improves performance',
emoji: '⚡️',
value: 'perf',
},
refactor: {
description: 'A code change that neither fixes a bug or adds a feature',
emoji: '',
value: 'refactor',
},
release: {
description: 'Create a release commit',
emoji: '',
value: 'release',
},
style: {
description: 'Markup, white-space, formatting, missing semi-colons...',
emoji: '',
value: 'style',
},
test: {
description: 'Adding missing tests',
emoji: '',
value: 'test',
},
messages: {
type: "Select the type of change that you're committing:",
customScope: 'Select the scope this component affects:',
subject: 'Write a short, imperative mood description of the change:\n',
body: 'Provide a longer description of the change:\n ',
breaking: 'List any breaking changes:\n',
footer: 'Issues this commit closes, e.g #123:',
confirmCommit: 'The packages that this commit has affected\n',
},
},
};
pnpm commit
参考文章
我的项目地址
商业转载请联系本人,非商业转载请注明出处。