六维教程

Vite 实战项目

前面十一篇把 Vite 的各个知识点拆开了讲,这一篇我们用一个完整的小项目把它们串起来。目标是搭一个「待办事项」应用,集成 TypeScript、路径别名、环境变量、代码分割和部署配置。

需求与技术选型

功能很简单,一个可以添加、完成、删除待办项的页面。技术选型如下。

  • 构建工具 Vite 7
  • 框架 Vue 3 + TypeScript
  • 样式原生 CSS(保持简单,聚焦 Vite 本身)
  • 数据存 localStorage,无需后端

初始化与目录规划

创建项目:

npm create vite@latest todo-app -- --template vue-ts
cd todo-app
npm install

规划目录:

src/
├── main.ts
├── App.vue
├── components/
│   ├── TodoInput.vue
│   └── TodoList.vue
├── composables/
│   └── useTodos.ts
└── utils/
    └── id.ts

配置 TypeScript 与路径别名

vite.config.ts 加上 @ 别名:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

tsconfig.json 同步:

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

编写核心逻辑

用组合式函数管理待办数据,放在 @/composables/useTodos.ts

import { ref } from 'vue'
import { genId } from '@/utils/id'

export interface Todo {
  id: number
  text: string
  done: boolean
}

const STORAGE_KEY = 'vite-todo'

export function useTodos() {
  const todos = ref<Todo[]>(load())

  function load(): Todo[] {
    return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
  }

  function save() {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(todos.value))
  }

  function add(text: string) {
    todos.value.push({ id: genId(), text, done: false })
    save()
  }

  function toggle(id: number) {
    const item = todos.value.find(t => t.id === id)
    if (item) item.done = !item.done
    save()
  }

  function remove(id: number) {
    todos.value = todos.value.filter(t => t.id !== id)
    save()
  }

  return { todos, add, toggle, remove }
}

App.vue 组合组件:

<script setup lang="ts">
import TodoInput from '@/components/TodoInput.vue'
import TodoList from '@/components/TodoList.vue'
import { useTodos } from '@/composables/useTodos'

const { todos, add, toggle, remove } = useTodos()
</script>

<template>
  <main>
    <h1>我的待办</h1>
    <TodoInput @add="add" />
    <TodoList :todos="todos" @toggle="toggle" @remove="remove" />
  </main>
</template>

环境变量与多环境

新建 .env.env.production

# .env
VITE_APP_TITLE = 我的待办
# .env.production
VITE_APP_TITLE = 我的待办(生产)

在代码里读取:

const title = import.meta.env.VITE_APP_TITLE

本地开发用 npm run dev,构建用 npm run build,两者的标题可以通过环境变量区分。

代码分割

如果后续加入统计页等独立模块,用动态导入让它单独成 chunk:

const Stats = () => import('@/components/Stats.vue')

这样只有进入统计页时才加载对应代码,首屏更轻。

构建优化与部署

考虑把 Vue 单独拆包,编辑 vite.config.ts

export default defineConfig({
  plugins: [vue()],
  resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } },
  build: {
    rollupOptions: {
      output: {
        manualChunks: { vue: ['vue'] }
      }
    }
  }
})

构建并预览:

npm run build
npm run preview

确认无误后部署。若部署到 GitHub Pages 子路径,记得设 base: '/仓库名/' 再重新构建。

复盘总结

通过这个小项目,我们实际用到了:

  • 脚手架创建与别名配置(第 3、5、9 篇)
  • 组件化与 TypeScript 类型(第 9 篇)
  • 环境变量多环境区分(第 7 篇)
  • 动态导入做代码分割(第 10 篇)
  • 构建与预览部署(第 8 篇)

到这里,你已经具备用 Vite 独立开发一个规范前端项目的能力。后续可以继续深入插件开发、测试集成、Monorepo 等方向,不断把工具链打磨得更顺手。

祝你的 Vite 之旅顺利。

上一篇
Vite 库模式