Skip to content

Vite 项目配置笔记 ​

从零搭建 Vue 3 + TypeScript 工程:类型与路径别名、ESLint / Prettier、提交规范、路由与状态管理、SCSS、Element Plus、环境变量、axios、HTTPS、代理与打包优化。

一、初始化项目 ​

1. Node 版本要求 ​

Node 版本要求 v18.19.0。

2. VS Code 插件 ​

  • Vue - Official(开发 Vue 2 时需确保禁用 Vetur 插件,两者会冲突)
  • Prettier - Code formatter
  • ESLint

3. 创建项目 ​

bash
npm create vite@latest my-vue-app -- --template vue-ts

4. 安装项目依赖 ​

bash
yarn

二、配置 tsconfig ​

1. 新建 src/typings.d.ts ​

在 src 目录下新建 typings.d.ts,声明全局类型:

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

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

2. 增加类型检查脚本 ​

修改 package.json:

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

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

3. 提示:配置未生效时重启 TS 服务 ​

遇到 TS 报错,有时是配置未生效,可以重启 VS Code 或 TS 服务:Ctrl + Shift + P 调出命令面板,输入 Restart TS Server。

三、配置路径别名 ​

1. 安装类型声明 ​

bash
yarn add @types/node -D

2. 修改 vite.config.ts ​

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
    },
  },
});

3. 修改 tsconfig.app.json ​

jsonc
{
  "compilerOptions": {
    // 新增
    "baseUrl": ".", // 查询的基础路径
    "paths": {
      "@/*": ["src/*"], // 路径映射,配合别名使用
    },
  },
}

四、配置 ESLint 与 Prettier ​

1. 安装依赖 ​

bash
# 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@^7.11.0 -D

# eslint ts 默认规则补充
yarn add @typescript-eslint/eslint-plugin@^7.11.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 ​

js
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 Rules。

3. 新建 .prettierrc ​

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

4. 新建 .prettierignore ​

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

node_modules
dist

5. 让配置生效 ​

先重启 VS Code 使配置生效。

此时会发现 App.vue 的 import 处飘红,因为语句结尾没有使用分号。在 package.json 中新增 lint 脚本:

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

运行 yarn run lint,上述 eslint(prettier/prettier) 问题都会被修复。

五、ESLint V9 配置 ​

1. 初始化配置 ​

bash
npm init @eslint/config

根据提示安装相应插件,会生成 eslint.config.js。

npm init @eslint/config 的交互式选择过程

2. 安装 Prettier 相关插件 ​

提示生成的插件中已包含 ESLint、Vue、TypeScript,因此还需单独安装 Prettier:

bash
# eslint prettier 插件安装
yarn add eslint-plugin-prettier -D

# 用来解决与 eslint 的冲突
yarn add eslint-config-prettier -D

# 安装 prettier
yarn add prettier -D

3. 引入 Prettier 推荐配置 ​

js
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";

export default [
  // ...
  eslintPluginPrettierRecommended,
];

4. 完整配置示例 ​

js
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginVue from "eslint-plugin-vue";
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";

export default [
  {
    files: ["src/**/*.{js,mjs,cjs,ts,vue}"],
  },
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  ...pluginVue.configs["flat/essential"],
  {
    files: ["**/*.vue"],
    languageOptions: { parserOptions: { parser: tseslint.parser } },
  },
  eslintPluginPrettierRecommended,
  /* 当多个配置对象指定相同的规则时,规则配置将与后一个对象合并,并优先于任何先前的对象,
     因此自定义 rules 需放到配置最后 */
  {
    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
    },
  },
  /* 根据业务需求,自定义忽略的配置文件 */
  {
    ignores: ["src/assets/icon/*"],
  },
];

5. 修改 lint 脚本 ​

V9 已移除 --ext 参数,改为在配置文件里用 files 声明匹配范围:

jsonc
"scripts": {
  "lint": "eslint src --fix --report-unused-disable-directives --max-warnings 0"
}

运行 yarn run lint,上述 eslint(prettier/prettier) 问题都会被修复。

六、配置 husky、lint-staged 与 commitlint ​

1. 三个工具的作用 ​

  • husky:为 git 客户端增加 hook 的工具
  • lint-staged:仅对 Git 暂存区文件进行处理,配合 husky 使用
  • @commitlint/cli:让 commit 信息规范化

2. 创建仓库并安装 ​

bash
# 创建 git 仓库
git init

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 文件夹 ​

bash
npx husky install

4. 修改 .husky/pre-commit ​

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

5. 修改 .husky/commit-msg ​

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

6. 配置 lint-staged ​

修改 package.json:

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

7. 新建 commitlint.config.cjs ​

提示:由于 package.json 中的 "type": "module",CommonJS 文件需要显式声明为 .cjs。

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

8. 提交信息格式 ​

text
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 提交

9. 提交示例 ​

bash
# 符合规范,提交成功
git commit -m 'feat: 增加 xxx 功能'

# type 不合法,提交失败
git commit -m 'bug: 修复 xxx 功能'

10. VS Code 保存自动格式化 ​

在 .vscode 下新建 settings.json:

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

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

七、配置路由 ​

路由的安装、路由表组织、导航守卫与传参方式见 Vue Router 3 使用笔记。

八、配置 Pinia ​

Pinia 的安装与使用待补充。

九、配置 SCSS ​

1. 安装 ​

bash
yarn add sass -D

2. 配置全局样式文件 ​

新建 src/assets/styles/index.scss:

scss
$test-color: red;

配置 vite.config.ts:

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

3. 在组件中使用 ​

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

重启项目,查看效果。

十、配置 Element Plus ​

1. 安装 ​

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

2. 安装按需引入插件 ​

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

3. 配置 vite.config.ts ​

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 中引入,插件会自动挂载处理,可以在全局直接使用;但图标需要手动全量注册。

ts
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);
}

十一、配置环境变量 ​

1. 新建环境文件 ​

  • .env:所有环境生效
  • .env.development:开发环境配置
  • .env.production:生产环境配置

2. 定义变量 ​

以 VITE_ 为前缀定义变量,否则不会暴露给客户端:

ini
VITE_BASE_URL = '//127.0.0.1:9000/api'

3. 补全变量类型 ​

修改 src/vite-env.d.ts:

ts
/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_BASE_URL: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

4. 使用变量 ​

ts
import.meta.env.VITE_BASE_URL;

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

通过 loadEnv 读取:

ts
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 的内容。

6. 自定义模式 ​

修改 package.json:

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

yarn test 启动时,读取 .env 与 .env.test 的内容。

7. 判断当前环境 ​

ts
import.meta.env.MODE;

十二、配置 axios ​

1. 安装 ​

bash
yarn add axios

2. 新建 utils/axios.ts ​

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 ​

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

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 ​

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. 使用 ​

vue
<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。

十三、开启 HTTPS ​

1. 下载 mkcert ​

从 mkcert releases 下载,目前版本 v1.4.4。

2. 安装根证书 ​

用 cmd 进入下载目录后执行:

bash
.\mkcert-v1.4.4-windows-amd64.exe -install

3. 查看是否安装成功 ​

bash
.\mkcert-v1.4.4-windows-amd64.exe --help

4. 生成自签证书 ​

bash
.\mkcert-v1.4.4-windows-amd64.exe localhost 127.0.0.1

在 mkcert 软件同目录下会生成自签证书。

5. 放到项目 certs 目录 ​

在项目根目录下创建 certs 文件夹,将刚生成的证书放进去。

6. 修改 vite.config.ts ​

ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import fs from "fs";

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    https: {
      key: fs.readFileSync("certs/localhost+1-key.pem"),
      cert: fs.readFileSync("certs/localhost+1.pem"),
    },
  },
});

十四、配置端口与代理 ​

修改 vite.config.ts:

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

十五、打包配置 ​

修改 vite.config.ts。

1. 手动分包 ​

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

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

2. 生成 .gz 文件 ​

安装插件:

bash
yarn add vite-plugin-compression -D

默认情况下插件在开发(serve)和生产(build)模式中都会调用,可用 apply 属性指明仅在构建时调用:

ts
import viteCompression from 'vite-plugin-compression'

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

3. 分离 js 与 css 目录 ​

ts
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. 分析产物体积 ​

安装:

bash
yarn add rollup-plugin-visualizer -D

配置:

ts
import { visualizer } from 'rollup-plugin-visualizer'

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

十六、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 是否存在都会被忽略。

ts
// 在 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
new URL("../assets/images/home.png", import.meta.url).href;

2. 组件自动注册 ​

webpack 通过 require.context 读取目录:

js
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,
};

Vite 通过 import.meta.glob:

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

3. __dirname 替换 ​

在 webpack 中可以直接使用 __dirname 代表当前资源目录,在 Vite 的 ES Module 中需要替换为:

ts
import { fileURLToPath } from "url";

const __filenameNew = fileURLToPath(import.meta.url);

const __dirname = path.dirname(__filenameNew);