Vite5.3+Typescript+Vue3+Pinia 最新搭建企业级前端项目

54,060 阅读4分钟

云在前端公众号中发送vite领取源码地址

2024/07/29更新:文章配置已更新至vite最新版本5.3.4,源码的vite版本是5.0.4,后续会更新源码

1. 初始化项目

1. node版本要求

node:v18.19.0

2. vscode插件安装

Vue - Official,Prettier - Code formatter,ESlint

提示:确保开发vue2时的Vetur插件禁用

3. 创建项目

npm create vite@latest vite-vue-ts-seed -- --template vue-ts

提示:vscode在文件中通过鼠标右击,选择使用...格式化文档,将prettier插件设为默认值

4. 安装项目依赖

yarn

2. 配置 tsconfig

1. 新建 src/typings.d.ts(在src文件夹下新建)

//声明window上自定义属性,如事件总线
declare interface Window {
  eventBus: any;
}

//声明.vue文件
declare module "*.vue" {
  import { DefineComponent } from "vue";
  const component: DefineComponent<object, object, any>;
  export default component;
}

提示:遇到ts报错,有些时候是配置未生效,可以重启vscode或ts服务(vscode快捷键 ctrl+shift+p调出命令行,输入Restart TS Server)

2. 修改package.json

"scripts": {
   "ts": "vue-tsc -b",
},

运行 yarn run ts 即可查看文件是否有ts类型错误

3. 配置路径别名

  1. 安装
yarn add @types/node -D
  1. 修改vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path"; //这个path用到了上面安装的@types/node

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  //这里进行配置别名
  resolve: {
    alias: {
      "@": path.resolve("./src"), // @代替src
    },
  },
});
  1. 修改tsconfig.app.json
{
  "compilerOptions":{
      //新增
      "baseUrl": ".", //查询的基础路径
      "paths": { "@/*": ["src/*"] }, //路径映射,配合别名使用
  }
}

4. 配置 ESLint 和 prettier

1. 安装

//eslint 安装
yarn add eslint@^8.39.0 -D

//eslint vue插件安装
yarn add eslint-plugin-vue@^9.11.0 -D

//eslint 识别ts语法
yarn add @typescript-eslint/parser@^6.19.0 -D

//eslint ts默认规则补充
yarn add @typescript-eslint/eslint-plugin@^6.19.0 -D

//eslint prettier插件安装
yarn add eslint-plugin-prettier@^5.1.3 -D

//用来解决与eslint的冲突
yarn add eslint-config-prettier@^9.1.0 -D 

//安装prettier
yarn add prettier@^3.2.4 -D

2. 新建.eslintrc.cjs

module.exports = {
  env: {
    browser: true,
    node: true,
    es2021: true,
  },
  parser: "vue-eslint-parser",
  extends: [
    "eslint:recommended", //继承 ESLint 内置的推荐规则
    "plugin:vue/vue3-recommended", // 继承 Vue.js 3 的推荐规则
    "plugin:@typescript-eslint/recommended", //继承 TypeScript ESLint 插件的推荐规则
    "plugin:prettier/recommended", //继承 Prettier 的推荐规则
    "eslint-config-prettier", //关闭 ESLint 中与 Prettier 冲突的规则
  ],
  parserOptions: {
    ecmaVersion: "latest",
    parser: "@typescript-eslint/parser",
    sourceType: "module",
    ecmaFeatures: {
      jsx: true,
    },
  },
  ignorePatterns: ["dist", "node_modules", ".eslintrc.cjs", "commitlint.config.cjs"],
  plugins: ["vue", "@typescript-eslint", "prettier"],
  rules: {
    "vue/multi-word-component-names": "off", // 禁用vue文件强制多个单词命名
    "@typescript-eslint/no-explicit-any": "off", //允许使用any
    "@typescript-eslint/no-this-alias": [
      "error",
      {
        allowedNames: ["that"], // this可用的局部变量名称
      },
    ],
    "@typescript-eslint/ban-ts-comment": "off", //允许使用@ts-ignore
    "@typescript-eslint/no-non-null-assertion": "off", //允许使用非空断言
    "no-console": [
      //提交时不允许有console.log
      "warn",
      {
        allow: ["warn", "error"],
      },
    ],
    "no-debugger": "warn", //提交时不允许有debugger
  },
};

rules更多配置:eslint.org/docs/latest…

3. 新建 .prettierrc

{
    "endOfLine": "auto",
    "printWidth": 120,
    "semi": true,
    "singleQuote": true,
    "tabWidth": 2,
    "trailingComma": "all",
    "bracketSpacing": true
}

4. 新建 .prettierignore

# 忽略格式化文件 (根据项目需要自行添加)
node_modules
dist

5. 重启vscode使配置生效

6. 配置package.json

可以看到App.vue文件在import处飘红,因为结尾没有使用分号

B257E9EA9CBE491DA0258FF814C44658.jpg

修改package.json

"scripts": {
    "lint": "eslint src --fix --ext .js,.ts,.vue --report-unused-disable-directives --max-warnings 0"
},

运行 yarn run lint,可以看到上述eslint(prettier/prettier)问题都将被修复

5. 配置 husky、lint-staged、@commitlint/cli

husky:一个为git客户端增加hook的工具

lint-staged:仅对Git 代码暂存区文件进行处理,配合husky使用

@commitlint/cli:让commit信息规范化

1. 创建git仓库

git init

2. 安装

yarn add husky@9.1.3 -D 

yarn add lint-staged@^15.2.7 -D

yarn add @commitlint/cli@^19.3.0 -D

yarn add @commitlint/config-conventional@^19.2.2 -D

3. 生成 .husky 的文件夹

npx husky install

4. 修改.husky/pre-commit

#!/usr/bin/env sh
npx --no-install lint-staged

5. 修改.husky/commit-msg

#!/usr/bin/env sh
npx --no-install commitlint --edit $1

6. 修改package.json

"lint-staged": {
  "src/**/*.{js,ts,vue}": [
    "yarn run lint",
    "prettier --write"
  ]
}

7. 新建commitlint.config.cjs

提示:由于package.json的"type": "module",需将commonjs文件显示声明为.cjs

module.exports = {
  extends: ['@commitlint/config-conventional'],
};

提交格式:

git commit -m <type>[optional scope]: <description> //注意冒号后面有空格
- type:提交的类型(如新增、修改、更新等)
- optional scope:涉及的模块,可选
- description:任务描述

type类型:

类别含义
feat新功能
fix修复 bug
style样式修改(UI校验)
docs文档更新
refactor重构代码(既没有新增功能,也没有修复 bug)
perf优化相关,比如提升性能、体验
test增加测试,包括单元测试、集成测试等
build构建系统或外部依赖项的更改
ci自动化流程配置或脚本修改
revert回退某个commit提交

8. 示范(非规范提交,将提交失败)

git commit -m 'feat: 增加 xxx 功能'
git commit -m 'bug: 修复 xxx 功能'

6. vscode 保存自动格式化

在.vscode下新建 settings.json

{
  "editor.codeActionsOnSave": {
    "source.fixAll": "explicit"
  }
}

之后每次文件有修改,保存时,都会自动格式化

7. 配置路由

vue-router(4.1.6)最新使用指南

8. 配置 pinia

pinia(2.0.34) 最新使用指南与持久化缓存

受限于篇幅原因,我把路由和pinia单独发了两篇文章

9. 配置scss

1. 安装

yarn add sass -D

2. 配置全局 scss 样式文件

新建 src/assets/styles/index.scss

$test-color: red;

配置vite.config.ts

css: {
    preprocessorOptions: {
      scss: {
        additionalData: '@import "@/assets/styles/index.scss";',
      },
    },
  },

组件中使用

<style lang="scss">
body {
  color: $test-color;
}
</style>

重启项目,查看效果

10. 配置 element-plus

1. 安装

yarn add element-plus @element-plus/icons-vue

2. 按需引入插件

yarn add unplugin-vue-components unplugin-auto-import -D

3. 配置vite.config.ts

// 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()],
    }),
  ],
})

4. 在main.ts引入

注意:按需引入时element-plus不需要在main.ts中引入,插件会自动挂载处理,可以在全局直接使用

这里在main.ts中引入element-plus样式与图标

import * as ElementPlusIconsVue from '@element-plus/icons-vue'; //引入图标
import 'element-plus/dist/index.css'; //引入样式

//...

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component);
}

11. 配置环境变量

新建 .env(所有环境生效).env.development(开发环境配置) .env.production(生产环境配置)

1. 定义变量

以 VITE_ 为前缀定义变量

VITE_BASE_URL = '//127.0.0.1:9000/api'

2. 定义变量ts类型

修改vite-env.d.ts

/// <reference types="vite/client" />
interface ImportMetaEnv {
  readonly VITE_BASE_URL: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

3. 使用变量

import.meta.env.VITE_BASE_URL

4. 在vite.config.ts中使用环境变量

使用 loadEnv 读取环境变量

import { defineConfig, loadEnv } from 'vite';
//...

export default ({ mode }) => {
  console.log('mode', loadEnv(mode, process.cwd()).VITE_BASE_URL); //127.0.0.1:9000/api  
  return defineConfig({
      //...
  });
};

使用 yarn dev 启动命令,读取.env 与 .env.development的内容

修改package.json

  "scripts": {
    "test":"vite --mode test", //新增
  },

使用 yarn test 启动命令,读取.env 与 .env.test的内容

12. 配置axios

1. 安装

yarn add axios

2. 新建utils/axios.ts

import axios from 'axios';

/*
 * 创建实例
 * 与后端服务通信
 */
const HttpClient = axios.create({
  baseURL: import.meta.env.VITE_BASE_URL,
});

/**
 * 请求拦截器
 * 功能:配置请求头
 */
HttpClient.interceptors.request.use(
  (config) => {
    const token = '222';
    config.headers.authorization = 'Bearer ' + token;
    return config;
  },
  (error) => {
    console.error('网络错误,请稍后重试');
    return Promise.reject(error);
  },
);

/**
 * 响应拦截器
 * 功能:处理异常
 */
HttpClient.interceptors.response.use(
  (config) => {
    return config;
  },
  (error) => {
    return Promise.reject(error);
  },
);

export default HttpClient;

3. 新建apis/model/userModel.ts

定义请求参数类型与返回数据类型

//定义请求参数
export interface ListParams {
  id: number; //用户id
}

export interface RowItem {
  id: number; //文件id
  fileName: string; //文件名
}

//定义接口返回数据
export interface ListModel {
  code: number;
  data: RowItem[];
}

4. 新建apis/user.ts

import HttpClient from '../utils/axios';
import type { ListParams, ListModel } from './model/userModel';

export const getList = (params: ListParams) => {
  return HttpClient.get<ListModel>('/list', { params });
};

5. 使用

<script setup lang="ts">
import { getList } from '@/apis/user';

getList({ id: 2 });
</script>

在chrome的network中可以看到请求了http://127.0.0.1:9000/api/list?id=2

13. 配置端口与代理

修改vite.config.ts

export default defineConfig({
    ...
  server: {
    host: '0.0.0.0',
    port: 8080, 
    open: true,
    https: false,
    proxy: {
      '/api': {
        target: '要代理的地址',
        changeOrigin: true,
        ws: true,
        rewrite: (path: string) => path.replace(/^\/api/, ''),
      },
    },
  },
  });

14. 打包配置

修改vite.config.ts

1. 分包

通过() => import()形式加载的组件会自动分包,第三方插件需手动分包

build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vue: ['vue', 'pinia', 'vue-router'],
          elementIcons: ['@element-plus/icons-vue'],
        },
      },
    },
  },

2. 生成.gz文件

  1. 安装
yarn add vite-plugin-compression -D
  1. 修改vite.config.ts

默认情况下插件在开发 (serve) 和生产 (build) 模式中都会调用,使用 apply 属性指明它们仅在 'build' 或 'serve' 模式时调用

这里打包生成 .gz 插件仅需在打包时使用

import viteCompression from 'vite-plugin-compression'

  plugins: [
    //...
    {
      ...viteCompression(),
      apply: 'build',
    },
  ],

3. js和css文件夹分离

export default defineConfig({
    build: {
      rollupOptions: {
        output: {
          chunkFileNames: "static/js/[name]-[hash].js",
          entryFileNames: "static/js/[name]-[hash].js",
          assetFileNames: "static/[ext]/[name]-[hash].[ext]",
        },
      },
    },
  });

4. 分析生成包的大小

1.安装

rollup-plugin-visualizer
  1. 修改vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer';

  plugins: [
    //...
    visualizer({ open: true }),
  ],

15. vite与webpack使用区别

1. 静态资源处理

webpack:使用require处理

vite:使用 new URL(url, import.meta.url).href 处理

import.meta.url 包含了对于目前 ES 模块的绝对路径

new URL(url [, base]) 构造函数返回一个新创建的 URL 对象,如果url 是相对 URL,则会将 base 用作基准 URL。如果 url 是绝对 URL,则无论参数base是否存在,都将被忽略

new URL('../assets/images/home.png', import.meta.url).href

//在src/constants/menus.ts下引入图片
//import.meta.url返回 http://localhost:8080/src/constants/menus.ts

//new URL(...).href返回
//http://localhost:8080/src/assets/images/home.png

2. 组件自动化注册

webpack

<script>
const path = require('path');
//读取@/components/BaseEchartsModel下所有.vue文件
const files = require.context('@/components/BaseEchartsModel', false, /\.vue$/);
const modules = {};
files.keys().forEach((key) => {
  const name = path.basename(key, '.vue');
  modules[name] = files(key).default || files(key);
});
export default {
  name: 'BaseEcharts',
  components: modules,
};
</script>

vite

<script setup lang="ts">
//读取@/components/BaseEchartsModel下所有.vue文件
import.meta.glob('@/components/BaseEchartsModel/*.vue');
</script>

16. 结尾

想了解更多关于vue的,可在淘宝或京东搜索Vue.js 3编程艺术了解更多,作者曹文杰,封面如下所示。

或者直接访问京东 清华大学出版社官方旗舰店 购买

创作历程可参考我的另一篇文章:感谢掘金,我的书出版了 be1b693ad52ed7b9e4e403d77e4f665.jpg