搭建 Vite+Vue3 项目模板

236 阅读6分钟

创建 Vite 项目

Vite 官方中文文档

cnpm create vite@latest

√ Project name: ... vue3-vite
√ Select a framework: » Vue
√ Select a variant: » TypeScript

cd vue3-vite
cnpm install
npm run dev

项目目录结构

│  ├─public # 静态资源目录
│  │      favicon.ico
│  │
│  ├─src
│  │  │  App.vue # 入口vue文件
│  │  │  main.ts # 入口文件
│  │  │  vite-env.d.ts # vite环境变量声明文件
│  │  │
│  │  ├─assets # 资源文件目录
│  │  │      logo.png
│  │  │
│  │  └─components # 组件文件目录
│  │         HelloWorld.vue
│  │
│  │ .gitignore
│  │ index.html # Vite项目的入口文件
│  │ package.json
│  │ README.md
│  │ tsconfig.json # tsconfig配置文件
│  │ vite.config.ts # vite配置文件

配置别名

通过配置 vite.config.ts 和 tsconfig.json 来实现别名。

vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import * as path from "path";

// https://vitejs.dev/config/
export default defineConfig({
  resolve: {
    //设置别名
    alias: {
      "@": path.resolve(__dirname, "src"),
    },
  },
  plugins: [vue()],
});

此时,我们会发现这行代码会报错。import * as path from "path"; 找不到模块“path”或其相应的类型声明。这是因为我们的配置文件是 ts 类型。只需要安装 Node.js 类型检查包就好。

cnpm install -D @types/node

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "lib": ["esnext", "DOM", "DOM.Iterable"],
    /** 路径别名 */
    "baseUrl": "./",
    "paths": {
      "@": ["src"],
      "@/*": ["src/*"]
    },
    /* Bundler mode */
    "moduleResolution": "node",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "strict": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "noFallthroughCasesInSwitch": false
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.vue"
  ],
  "references": [
    {
      "path": "./tsconfig.node.json"
    }
  ]
}

集成 Vue Router

router.vuejs.org/zh/

安装 vue-router

cnpm i vue-router@4

使用 vue-router

│  ├─src
│  │  ├─router # 路由资源文件目录
│  │  │    │  index.ts
│  │  ├─views # 视图文件目录

src/router/index.ts

import { RouteRecordRaw, createRouter, createWebHistory } from "vue-router";

const routes: Array<RouteRecordRaw> = [
  { path: "/", redirect: "/home" },

  { path: "/home", name: "Home", component: () => import("@/views/Home.vue") },
  { path: "/demo", name: "Demo", component: () => import("@/views/Demo.vue") },
];

const router = createRouter({
  // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
  history: createWebHistory(),
  routes, // `routes: routes` 的缩写
});

export default router;
// views/Home.vue
<template>
  <div>HOME</div>
</template>

<script setup lang="ts"></script>

// views/Demo.vue
<template>
  <div>DEMO</div>
</template>

<script setup lang="ts"></script>

// App.vue
<script setup lang="ts"></script>

<template>
  <RouterView />
</template>

<style scoped>
  #app {
    width: 100vw;
    height: 100vh;
  }
</style>

在 vue 中使用路由。 main.ts

import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import router from "./router";

const app = createApp(App);

app.use(router);

app.mount("#app");

集成 Pinia

pinia.web3doc.top/introductio…

安装 Pinia

cnpm i pinia

使用 Pinia

与 router 一样,先在 src 目录下创建 store 文件夹,来存放相关的数据状态文件。 目录结构

│  ├─src
│  │  ├─store # 数据状态文件目录
│  │  │    │  index.ts
│  │  │    ├─ modules
│  │  │    │     │   user.ts
// 创建pinia实例
// store/index.ts
import { createPinia } from "pinia";

const store = createPinia();

export default store;

// 定义user数据
// store/modules/user.ts
import { defineStore } from 'pinia'

// 第一个参数是应用程序中 store 的唯一 id
const useUserStore = defineStore('user', {
    state: () => {
        return {
            name: 'hps',
        }
    },
    // other options...
})

export default useUserStore

// 在vue中使用pinia
// main.ts

import store from "./store";

app.use(store);

// 使用user数据
// App.vue
<script setup lang="ts">
import useUserStore from "@/store/modules/user";

const userStore = useUserStore();
</script>

<template>
  <div>{{ userStore.name }}</div>
  <RouterView />
</template>

<style scoped>
#app {
  width: 100vw;
  height: 100vh;
}
</style>

代码质量和代码风格

集成 ESLint


cnpm i eslint --save-dev

cnpm init @eslint/config --save-dev

√ How would you like to use ESLint? · problems
√ What type of modules does your project use? · esm  // javascript
√ Which framework does your project use? · vue     // vue
√ Does your project use TypeScript? · No / Yes   // yes
√ Where does your code run? · browser, node     // brower/node
√ What format do you want your config file to be in? · JSON   // json
The config that you've selected requires the following dependencies:

@typescript-eslint/eslint-plugin@latest eslint-plugin-vue@latest @typescript-eslint/parser@latest
√ Would you like to install them now? · No / Yes
√ Which package manager do you want to use? · npm

cnpm i @typescript-eslint/eslint-plugin@latest eslint-plugin-vue@latest @typescript-eslint/parser@latest --save-dev

devDependencies:
+ @typescript-eslint/eslint-plugin latest
+ eslint-plugin-vue latest
+ @typescript-eslint/parser latest

.eslintrc.json 文件

{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:vue/vue3-essential"
  ],
  "parserOptions": {
    "ecmaVersion": "latest",
    "parser": "@typescript-eslint/parser",
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint", "vue"],
  "rules": {}
}

我们还需要在 package.json 中,给我们的 ESLint 配置脚本指令

  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "preview": "vite preview",
    "eslint": "eslint src --ext .js,.vue,.ts,.jsx,.tsx --ignore-path .gitignore --fix"
  },

但此时,我们会发现 ESLint 无法对 vue 文件中的 template 进行校验修复。我们查看 vue 文档得知:我们还需要配置 parser 来解析 vue 文件

cnpm i eslint-plugin-vue --save-dev

修改.eslintrc.json 文件

{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    // vue 规则
    "plugin:vue/vue3-recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  // 添加 vue文件解析器  解析template文件
  "parser": "vue-eslint-parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "parser": "@typescript-eslint/parser",
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint", "vue"],
  "rules": {
    // 自定义规则
  }
}

集成 Prettier

虽然 ESLint 可以检查代码风格,但它并不会自动格式化代码。而 Prettier 专注于代码格式化,但不会检查代码错误。所以我们这里还需要引进 Prettier 来做代码美化。

cnpm i --save-dev prettier
/** .prettierrc.js
 * 在VSCode中安装prettier插件 打开插件配置填写`.prettierrc.js` 将本文件作为其代码格式化规范
 * 在本文件中修改格式化规则,不会同时触发改变ESLint代码检查,所以每次修改本文件需要重启VSCode,ESLint检查才能同步代码格式化
 * 需要相应的代码格式化规范请自行查阅配置,下面为默认项目配置
 */
module.exports = {
  // 一行最多多少个字符
  printWidth: 150,
  // 指定每个缩进级别的空格数
  tabWidth: 2,
  // 使用制表符而不是空格缩进行
  useTabs: false,
  // 在语句末尾是否需要分号
  semi: false,
  // 是否使用单引号
  singleQuote: true,
  // 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
  quoteProps: "as-needed",
  // 在JSX中使用单引号而不是双引号
  jsxSingleQuote: false,
  // 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
  trailingComma: "es5",
  // 在对象文字中的括号之间打印空格
  bracketSpacing: true,
  // jsx 标签的反尖括号需要换行
  jsxBracketSameLine: false,
  // 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
  arrowParens: "always",
  // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
  rangeStart: 0,
  rangeEnd: Infinity,
  // 指定要使用的解析器,不需要写文件开头的 @prettier
  requirePragma: false,
  // 不需要自动在文件开头插入 @prettier
  insertPragma: false,
  // 使用默认的折行标准 always\never\preserve
  proseWrap: "preserve",
  // 指定HTML文件的全局空格敏感度 css\strict\ignore
  htmlWhitespaceSensitivity: "css",
  // Vue文件脚本和样式标签缩进
  vueIndentScriptAndStyle: false,
  //在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF),
  //然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
  //对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
  // 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
  endOfLine: "auto",
};
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "preview": "vite preview",
    "eslint": "eslint src --ext .js,.vue,.ts,.jsx,.tsx --ignore-path .gitignore ",
    "prettier": "prettier --write \"./**/*.{html,vue,ts,js,json,md}\""
  },

处理 ESLint 与 Prettier 冲突

在开发中,我们会经常遇到 prettier 与 ESLint 的配置存在冲突。
此时我们可以通过 eslint-config-prettiereslint-plugin-prettier 来避免这个问题。
eslint-config-prettier 是 ESLint 的配置,会关闭可能与 Prettier 冲突的 ESLint 规则。它允许你在项目中同时使用 ESLint 和 Prettier,而不会出现规则冲突的问题。 保将其放在 extends 队列最后,这样它将覆盖其他配置
eslint-plugin-prettier 是一个 ESLint 插件,它将 Prettier 的格式化功能集成到 ESLint 中。通过使用 eslint-plugin-prettier,你可以在 ESLint 中运行 Prettier 的格式化规则,并在代码检查过程中自动修复格式错误。

bash
# 安装 eslint-config-prettier
cnpm i --save-dev eslint-config-prettier
cnpm i --save-dev eslint-plugin-prettier

ESLint 配置文件

{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "plugin:vue/vue3-recommended",
    "plugin:@typescript-eslint/recommended",
    // 告诉 ESLint 关闭与 Prettier 格式化规则冲突的任何规则,需写在最后,会覆盖前面的配置
    "plugin:prettier/recommended"
  ],
  "parser": "vue-eslint-parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "parser": "@typescript-eslint/parser",
    "sourceType": "module"
  },
  "plugins": [
    "@typescript-eslint",
    "vue",
    // 将 Prettier 的格式化功能集成到 ESLint 中。会应用Prettier的配置
    "prettier"
  ],
  "rules": {
    // 自定义规则
  }
}

注意:上面的方法只能处理 extends 中的配置冲突。rules 中的冲突无法处理。我们一般会在 perttier 中统一我们的代码风格。在 eslint 中保证我们的代码质量。

{
  // 开启自动修复
  "editor.codeActionsOnSave": {
    "source.fixAll": "explicit",
    "source.fixAll.eslint": "explicit"
  },
  // 保存的时候自动格式化
  "editor.formatOnSave": true,
  // 默认格式化工具选择prettier
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  // 配置该项,新建文件时默认就是space:2
  "editor.tabSize": 2,
  "workbench.editor.enablePreview": false,
  "editor.unicodeHighlight.allowedCharacters": {
    " ": true
  },
  "cSpell.languageSettings": [
    
  ]
}