截止本文章编写vue已经更新到了vue3.3版本,使用的人也越来越多,再加上vue2已经写很长一段时间,所以决定尝试使用vue3和vite来创建个项目提升一下,本文章主要记录自己的一个搭建过程。
本文主要采用npm的构建方式,其他的构建方式可以参考 vite官网
创建项目
先检查本地nodejs版本,如果版本低于14.18,请先升级node版本,最好到16+ 再进行项目安装。
查看nodejs版本
node -v
开始创建
npm create vite@latest
如上一个最基础版本的vite-vue3的项目就已经初始化完成。
启动项目
安装依赖并启动
npm install
npm run dev
安装工具
1. 安装vue-router
npm install vue-router@4
// 创建 `src/router/index.ts` 文件(并创建view文件夹随便写2个页面方便写路由)
import { createRouter, RouteRecordRaw, createWebHashHistory } from 'vue-router';
const constantRoutes: Array<RouteRecordRaw> = [
{
path: '/index',
name: 'Index',
component: () => import('../view/index/index.vue'),
},
{
path: '/system',
name: 'System',
component: () => import('../view/system/system.vue'),
},
];
const router = createRouter({
history: createWebHashHistory(),
routes: constantRoutes,
});
export default router;
// main.ts 中引入router
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router).mount('#app');
App.vue 页面中使用<router-view />标签, 此时可以启动项目并查看我们的路由
2. 安装Pinia(状态储存-vuex的替代品)
npm install pinia
// 创建 `src/store/index.ts` 文件
import { defineStore } from 'pinia';
export const useMyStore = defineStore({
id: 'myStore',
state: () => ({
counter: 0,
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
actions: {
increment() {
this.counter++;
},
},
});
export default createPinia();
// main.ts 中引入store
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
import router from './router';
import store from './store';
const app = createApp(App);
app.use(router).use(store).mount('#app');
3. 安装Element Plus
// 这里采用按需引入,需要安装3个包
npm install element-plus --save
npm install -D unplugin-vue-components
npm install -D unplugin-auto-import
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
// https://vitejs.dev/config/
// 这里 defineConfig 采用函数式,方便以后项目配置
export default defineConfig(({ command, mode, ssrBuild }) => ({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}));
4. 安装Axios
npm install axios
在根目录下创建utils和api 两个文件夹
// 创建 `utils/http.ts` 文件
import axios, {
AxiosInstance,
InternalAxiosRequestConfig,
AxiosResponse,
} from 'axios';
/**
* 创建axios
*/
const http: AxiosInstance = axios.create({
baseURL: '',
timeout: 5000,
});
/**
* 请求拦截器
*/
http.interceptors.request.use((config: InternalAxiosRequestConfig) => {
console.log('这是请求拦截器');
return config;
});
/**
* 响应拦截器
*/
http.interceptors.response.use(
(response: AxiosResponse) => {
console.log('这是响应拦截器');
return response;
},
(error) => {
console.log('请求失败', error);
}
);
// 在 `api/user.ts` 中使用
import { AxiosPromise } from 'axios';
import http from '../utils/http';
export const userInfo = (params): AxiosPromise => {
return http({
url: 'userInfo',
method: 'get',
params
});
};
5. 安装sass
npm install --save-dev sass
npm install --save-dev sass-loader
项目规范类工具
1. 安装prettier
npm i prettier -D
// 创建 .prettierrc.cjs 规则文件,里面大致内容,更多参考官网
module.exports = {
// endOfLine: 'auto', // 允许代码结尾是回车或者换行,\n\r
printWidth: 120, // 换行字符串阈值
tabWidth: 2, // 水平缩进的空格数
useTabs: false,
semi: false, // 句末是否加分号
vueIndentScriptAndStyle: true,
singleQuote: true, // 用单引号
trailingComma: 'none', // 最后一个对象元素加逗号
bracketSpacing: true, // 对象,数组加空格
jsxBracketSameLine: true, // jsx > 是否另起一行
arrowParens: 'always' // (x) => {} 是否要有小括号
}
// 创建 .prettierignore 忽略规则文件,大致内容
/dist/*
.local
.output.js
commitlint.config.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
vscode 可以配合安装
Prettier - Code formatter进行格式化操作更方便
2. 安装eslint
/**
* 这里安装的包很多
* eslint: eslint 主要核心代码
* eslint-config-prettier: 解决eslint和prettier冲突
* eslint-config-prettier: 将prettier作为eslnt规范
* eslint-plugin-vue: eslint的vue规范
* eslint-config-airbnb-base: 编码规范
* eslint-plugin-import: eslint-config-airbnb-base包安装前必须安装
* @typescript-eslint/parser: eslint的ts相关
* @typescript-eslint/eslint-plugin : eslint的ts相关
* eslint-import-resolver-alias :主要用户项目配置 @ 别名引入
*/
npm install eslint -D
npm install eslint-config-prettier -D
npm install eslint-plugin-prettier -D
npm install eslint-plugin-vue -D
npm install @typescript-eslint/parser -D
npm install @typescript-eslint/eslint-plugin -D
npm install eslint-plugin-import -D
npm install eslint-config-airbnb-base -D
npm install eslint-import-resolver-alias -D
// .eslintignore eslint 忽略文件
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
/src/mock
Dockerfile
commitlint.config.js
// eslint 配置文件
npm init @eslint/config
仅供参考
// 生成好的eslint规则文件大致如下
module.exports = {
env: {
browser: true,
es2021: true
},
extends: ['eslint:recommended', 'plugin:vue/vue3-essential', 'plugin:@typescript-eslint/recommended'],
overrides: [],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: ['vue', '@typescript-eslint'],
rules: {
indent: ['error', 'tab'],
'linebreak-style': ['error', 'windows'],
quotes: ['error', 'single'],
semi: ['error', 'always']
}
}
3.项目使用@来引入文件(上面的项目目前都是通过 ./ 或者 ../ 引入的文件,我们现在配置成@别名)
// vite.config.ts 中新增resolve.alias和resolve.extensions配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
// 这里 defineConfig 采用函数式,方便以后项目配置
export default defineConfig(({ command, mode, ssrBuild }) => ({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@c': path.resolve(__dirname, 'src/components')
},
// 解析到文件之后自动添加如下拓展名,根据自己需求配置
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json']
}
}))
引入测试,可以找到文件
4. AutoImport 自动导入api配置
因为之前我们在导入element Plus的时候已经安装了unplugin-auto-import插件,这个插件可以帮我们自动导入vue3,vue-router等一些库中的api,不用再写 import {xxx} from xxx
1. 根目录下创建 .eslintrc-auto-import.json 文件
2. 修改vite.config,第一次配置的时候将 eslintrc.enabled 设置成 true
// 修改我们之前的vite.config.ts 中的AutoImport
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
dts: './auto-imports.d.ts',
resolvers: [ElementPlusResolver()],
eslintrc: {
enabled: false, // Default `false`
filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
}
}),
3. .eslintrc.cjs 文件中的 extends 属性中添加 './.eslintrc-auto-import.json',
4. tsconfig.json 文件中的include属性中添加 "./auto-imports.d.ts"
5. 重启项目
5. 一些格式化冲突以及配置
初步解决一些报错
1. 报错:Expected indentation of 2 tabs but found 4 spaces
这种类型的错误主要是eslint和prettier对于空格缩进的冲突,基于我们之前prettier的配置文件,可以将.eslintrc.cjs文件中rules.indent属性设置一下。
2. 报错:Parsing error: '>' expected.eslint
这个主要是针对 <script setup></script> 语法糖的报错,可以在.eslintrc.cjs中设置parser属性和parserOptions.parser属性
3. 报错:Expected linebreaks to be 'CRLF' but found 'LF'
这个主要和初始化 .eslintrc.cjs 初始化配置, 以及操作系统有关系, mac系统一般文件行尾序列为LF,windows系统为CRLF, 这个问题可以通过在vscode设置或者.eslintrc.cjs 文件中的 rules[linebreak-style]属性,建议设置成 unix。
4. .eslintrc.cjs文件第一行如果提示: 'module' is not defined.eslintno-undef
遇见这个问题在 .eslintrc.cjs的env属性中添加node: true即可
最后
到这里一个最基本的vue3 + ts + eslint + prettier的项目空壳就已经搭建好了
但是实际开发中 .eslintrc.cjs文件还需要做很多优化,这个空壳项目里面就不过多的处理了。
贴一个自己本地项目的.eslintrc.cjs,.prettierrc.cjs
// .eslintrc.cjs
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
globals: {
defineEmits: 'readonly',
defineProps: 'readonly'
},
parser: 'vue-eslint-parser',
extends: [
'./.eslintrc-auto-import.json',
'plugin:vue/vue3-recommended',
'eslint:recommended',
'airbnb-base',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
'plugin:import/recommended',
'plugin:import/typescript'
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
settings: {
'import/resolver': {
alias: {
map: [['@', './src']],
extensions: ['.ts', '.js', '.jsx', '.tsx'] // 可忽略的后缀名
}
}
},
plugins: ['vue', 'prettier', '@typescript-eslint', 'eslint-plugin-import'],
rules: {
'prettier/prettier': ['error'],
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
json: 'never'
}
],
'vue/no-mutating-props': 'off',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': ['error'],
'@typescript-eslint/no-var-requires': 0,
'vue/multi-word-component-names': 'off',
'@typescript-eslint/explicit-module-boundary-types': ['off'],
'@typescript-eslint/no-explicit-any': ['off'],
'no-param-reassign': [
'error',
{
props: true,
ignorePropertyModificationsFor: [
'e', // for e.returnvalue
'ctx', // for Koa routing
'req', // for Express requests
'request', // for Express requests
'res', // for Express responses
'response', // for Express responses
'state', // for vuex state
'axios'
]
}
]
}
}
// prettierrc.cjs
module.exports = {
// endOfLine: 'auto', // 允许代码结尾是回车或者换行,\n\r
printWidth: 120, // 换行字符串阈值
tabWidth: 2, // 水平缩进的空格数
useTabs: false,
semi: false, // 句末是否加分号
vueIndentScriptAndStyle: true,
singleQuote: true, // 用单引号
trailingComma: 'none', // 最后一个对象元素加逗号
bracketSpacing: true, // 对象,数组加空格
jsxBracketSameLine: true, // jsx > 是否另起一行
arrowParens: 'always' // (x) => {} 是否要有小括号
}