使用Vite搭建Vue3项目实践记录

2,096 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

之前有开发Vue3的项目,但在写代码的过程中一直没有总结搭建项目架构的记录

因此借着假期有时间,尝试重新搭建一次,并升级使用的模块,记录搭建过程及遇到的问题

开始搭建Vite项目

使用pnpm搭建项目pnpm create vite

  1. 输入项目名称
  2. 选择vue
  3. 选择vue-ts
  4. 最后安装相关依赖

vite-create.png

配置vite.config.ts

添加文件夹别名

首先安装@types/nodepnpm i -D @types/node

resolve: {
  alias: {
    "@": resolve(__dirname, "./src")
  }
},

同时也要告诉ts,@是什么意思,所以要在tsconfig.json中的compilerOptions选项添加

"baseUrl": "./",
"paths": {
  "@/*": ["src/*"]
}

配置eslint和prettier

安装eslint

首先安装eslint,在命令行打开项目目录,输入pnpm i eslint -D

安装完eslint之后,继续输入.\node_modules\.bin\eslint --init这样eslint会根据你的需要安装和配置.eslintrc.js文件

eslint1.png

这时候还需要安装两个eslint插件vite-plugin-eslinteslint-plugin-vue

在命令行输入pnpm i vite-plugin-eslint eslint-plugin-vue -D

然后在vite.config.ts中加入下面配置

import eslint from "vite-plugin-eslint";

vite.config.ts文件的plugins中添加eslint配置

eslint({
  cache: false,
  fix: false,
  include: ["src/**/*.ts", "src/**/*.vue"]
})

安装prettier

根据prettier官网安装和配置.prettierrc文件

pnpm install --save-dev --save-exact prettier

随后创建一个.prettierrc文件,在命令行输入echo {}> .prettierrc

依然是需要两个安装插件配合eslint,eslint-plugin-prettiereslint-config-prettier

配置文件

.eslintrc.js如下

module.exports = {
  parser: "vue-eslint-parser",
  env: {
    browser: true,
    node: true,
    es2021: true
  },
  extends: [
    "plugin:vue/vue3-recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier",
    "plugin:prettier/recommended"
  ],
  parserOptions: {
    ecmaVersion: 13,
    parser: "@typescript-eslint/parser",
    sourceType: "module"
  },
  plugins: ["vue", "@typescript-eslint", "prettier"],
  rules: {
    indent: ["error", 2],
    // 关闭驼峰命名规则
    "vue/multi-word-component-names": 0
  }
};

.prettierrc如下

{
  "singleQuote": false,
  "semi": true,
  "trailingComma": "none",
  "printWidth": 120,
  "arrowParens": "always",
  "tabWidth": 2,
  "endOfLine": "auto",
  "overrides": [
    {
      "files": ".prettierrc",
      "options": {
        "parser": "json"
      }
    },
    {
      "files": "*.vue",
      "options": {
        "parser": "vue",
        "printWidth": 120
      }
    }
  ]
}

使用Element plus

按需引入

安装Element Plus 使用pnpm install element-plus

根据官网教程,可以按需引入,安装以下两个插件

pnpm install -D unplugin-vue-components unplugin-auto-import

然后在vite.config.ts文件添加下列配置

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()],
    }),
  ],
  build: {
    chunkSizeWarningLimit: 1024,
    rollupOptions: {
      output: {
        chunkFileNames: 'static/js/[name]-[hash].js',
        entryFileNames: 'static/js/[name]-[hash].js',
        assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
        manualChunks: {
          elementPlus: ["element-plus"],
        }
      }
    }
  },
});

国际化处理

由于element plus默认是英文,所以需要把默认语言切换成中文

如果是全局引入,官网有说明,但是按需引入,我选择使用ConfigProvider组件

需要在app.vue文件中引入语言包,并使用ConfigProvider组件,并配置语言

<script setup lang="ts">
import { ElConfigProvider } from "element-plus";
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import HelloWorld from "./components/HelloWorld.vue";
const locale = zhCn;
</script>

<template>
  <el-config-provider :locale="locale">
    <img alt="Vue logo" src="./assets/logo.png" />
    <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
  </el-config-provider>
</template>

这时候语言就已经切换为中文了,若有其他方案也可以尝试

打包构建报错问题

配置完element puls之后,尝试打包构建,发现一大堆报错

需要在tsconfig.json的compilerOptions配置中中添加

"skipLibCheck": true

更多可以参考官方的vite模板

使用vue-router

vue全家桶必备路由管理工具, 安装vue-routerpnpm i -S vue-router

src目录下新建router文件夹,及在router文件夹下新建index.ts文件

接着在src目录下新建Home.vue文件,并修改路由文件index.ts

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

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "Home",
    component: () => import("@/Home.vue")
  },
  {
    path: "/login",
    name: "Login",
    component: () => import("@/Login.vue")
  },
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

并且要在main.ts文件使用该路由文件

import router from "./router";

const app = createApp(App);
app.use(router);
app.mount("#app");

最后在App.vue中使用router-view组件

<template>
  <el-config-provider :locale="locale">
    <router-view />
  </el-config-provider>
</template>

那么现在打开项目首页就应该是Home.vue文件的内容了

如果有eslint的警告可以在rules中添加'vue/multi-word-component-names': 0

如果遇到如下报错,需要使用defineAsyncComponent

The above dynamic import cannot be analyzed by vite.
See https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations for supported dynamic import formats. If this is intended to be left as-is, you can use the /* @vite-ignore */ comment inside the import() call to suppress this warning.

如下所示

const routes = [
  {
    path: "/",
    name: "Home",
    component: defineAsyncComponent(() => import("@/index.vue"))
  },
];

使用Pinia

Pinia作为新一代的Vue状态管理工具,更适用于Vue3+TS的项目

依旧是安装pnpm i -S pinia,在src目录下新建store文件夹,及其user.ts文件

可以创建多个ts文件,分别新建不同的状态仓库

main.ts文件中使用pinia

import { createPinia } from "pinia";

app.use(createPinia());

user.ts内容如下,简单配置一个state

import { defineStore, acceptHMRUpdate } from "pinia";

export const useUserStore = defineStore("user", {
  state: () => ({
    userName: "Elvis"
  })
});

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot));
}

Home.vue中调用state的属性

<script setup lang="ts">
import { useUserStore } from "@/store/user";
const user = useUserStore();
</script>

<template>
  <div>
    home
    {{ user.userName }}
  </div>
</template>

更多的Pinia配置内容,可以到Pinia官网查看

使用Axios

个人还是没有用Class封装axios的习惯,也许是能力达不到,目标还是对请求拦截和响应拦截做处理

首先还是要安装axiospnpm i axios -S,还有qs模块pnpm i qs @types/qs -D

qs模块可以在请求拦截时,Get和Post请求中对数组做处理,可以根据后端的需要选择是否加上该处理

新建utils文件夹,并新建request.ts

import axios from "axios";
import qs from "qs";
import { IObject } from "@/types/interface";
import { ElMessage } from "element-plus";

const baseURL = import.meta.env.VITE_APP_API?.toString();

const service = axios.create({
  baseURL: baseURL,
  timeout: 60 * 1000,
  withCredentials: true
});

service.interceptors.request.use((config: IObject) => {
    const token = localStorage.getItem("Token");
    config.headers["token"] = token;
    // get请求传递数组
    if (config.method?.toUpperCase() === "GET") {
      config.paramsSerializer = function (params: unknown) {
        return qs.stringify(params, { arrayFormat: "comma" });
      };
    }
    // post请求数组传string
    if (config.method?.toUpperCase() === "POST") {
      config.data = qs.stringify(config.data);
    }
    return config;
  },
  (error) => {
    // 请求错误
    return Promise.reject(error);
  }
);

service.interceptors.response.use((response) => {
    const res = response.data as IObject;
    if (res.code && res.code !== 0) {
      // token过期处理
      if (res.code === 401 || res.code === 4001) {
        // return redirectLogin();
      }
      return ElMessage(`请求失败,${res.msg}`);
    } else {
      return res;
    }
  },
  (error) => {
    console.log(error);
  }
);

export default service;

baseUrl取的是.env配置文件的值,可以新建不同环境的.env文件,配置不同的接口ip

以上配置比较简约,可更具需求添加相关配置

使用husky

待续

使用postcss

待续

代码仓库地址

LWH/vite-vue3-project (gitee.com)

参考文章

  1. eslint 与 prettier 实现代码规范自动格式化 - 林来 - 博客园 (cnblogs.com)
  2. 基于Vite2+Vue3的项目复盘总结 - 掘金 (juejin.cn)
  3. element-plus/element-plus-vite-starter: 🌰 A starter kit for Element Plus with Vite (github.com)
  4. Vite2.0打包element-plus UI报错 - 前端-大雄 - 博客园 (cnblogs.com)
  5. Pinia进阶:优雅的setup(函数式)写法+封装到你的企业项目 - 掘金 (juejin.cn)