Vue 应用完整启动链路

可以串成一条完整的 Vue 应用启动链路。先记住这张图:

text 复制代码
浏览器访问 /
     ↓
index.html
     ↓
<script type="module" src="/src/main.ts">
     ↓
main.ts
     ↓
createApp(App)
     ↓
App.vue
     ↓
其他 Vue 组件

而 Vite 在旁边负责:

text 复制代码
读取 package.json
读取 vite.config.ts
解析 TS / Vue / CSS
把 .vue 转成浏览器能执行的 JS

下面逐个解释。


1. package.json 是干什么的?

来源 package.json 是一个 Node.js / npm 项目的项目清单文件

你可以把它理解成:

这个项目的"身份证 + 软件依赖清单 + 命令入口"。

典型 Vue 项目:

json 复制代码
{
  "name": "todo-list",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc -b && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "vue": "^3.5.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^6.0.0",
    "typescript": "~5.9.0",
    "vite": "^7.0.0"
  }
}

最重要的是三部分。

第一部分:项目信息

json 复制代码
{
  "name": "todo-list",
  "version": "1.0.0"
}

告诉 npm:

text 复制代码
这个项目叫什么
版本是多少

第二部分:scripts

json 复制代码
"scripts": {
  "dev": "vite",
  "build": "vite build"
}

所以执行:

bash 复制代码
npm run dev

本质就是:

bash 复制代码
vite

执行:

bash 复制代码
npm run build

本质就是:

bash 复制代码
vite build

所以:

npm run xxx 会去 package.jsonscripts 里找对应命令。

第三部分:dependencies

json 复制代码
"dependencies": {
  "vue": "^3.5.0"
}

表示项目运行依赖 Vue。

而:

json 复制代码
"devDependencies": {
  "vite": "...",
  "typescript": "...",
  "@vitejs/plugin-vue": "..."
}

主要是开发、编译、构建阶段使用的工具。

因此可以这样记:

text 复制代码
package.json

项目是谁?
    ↓
name / version

怎么运行?
    ↓
scripts

依赖什么?
    ↓
dependencies / devDependencies

2. vite.config.ts 是干什么的?

来源 它是 Vite 的配置文件

最简单的 Vue 项目通常是:

ts 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
})

这里最关键的一句:

ts 复制代码
plugins: [vue()]

意思是:

给 Vite 安装 Vue 支持。

因为原始 Vite 并不是天然就能处理:

text 复制代码
.vue

文件。

需要:

text 复制代码
@vitejs/plugin-vue

来处理。

除此之外,vite.config.ts 还能配置很多工程能力。

例如路径别名:

ts 复制代码
export default defineConfig({
  resolve: {
    alias: {
      '@': '/src'
    }
  }
})

于是:

ts 复制代码
import Todo from '@/components/Todo.vue'

代替:

ts 复制代码
import Todo from '../../../components/Todo.vue'

还可以配置开发服务器:

ts 复制代码
server: {
  port: 3000
}

代理:

ts 复制代码
server: {
  proxy: {
    '/api': {
      target: 'http://localhost:8080'
    }
  }
}

构建:

ts 复制代码
build: {
  outDir: 'dist'
}

所以一句话:

vite.config.ts 决定 Vite "怎么开发、怎么解析代码、怎么打包"。


3. index.html 为什么放在 src 外面?

这是一个很值得理解的问题。

首先:

来源 在 Vite 中,index.html 不只是普通静态文件,而是应用入口的一部分

你的目录通常是:

text 复制代码
todo-list/
│
├─ index.html
├─ package.json
├─ vite.config.ts
│
└─ src/
   ├─ main.ts
   ├─ App.vue
   └─ components/

打开 index.html

html 复制代码
<!doctype html>
<html>
  <head>
    <title>Todo App</title>
  </head>

  <body>
    <div id="app"></div>

    <script
      type="module"
      src="/src/main.ts">
    </script>
  </body>
</html>

关键:

html 复制代码
<script type="module" src="/src/main.ts"></script>

整个程序就是从这里开始进入 JS 世界的。

也就是说:

text 复制代码
index.html
    ↓
main.ts

为什么不放 src

因为 Vite 把:

text 复制代码
项目根目录/index.html

当作开发服务器的 HTML 入口。

比如你运行:

bash 复制代码
npm run dev

然后访问:

text 复制代码
http://localhost:5173/

Vite 默认对应:

text 复制代码
/index.html

而:

text 复制代码
src/

主要放:

应用源代码。

比如:

text 复制代码
src/
├── main.ts
├── App.vue
├── components/
├── views/
├── stores/
└── router/

所以两者职责不同:

text 复制代码
项目根目录
│
├── index.html
│      ↑
│    网页入口
│
└── src/
       ↑
     应用源码

推导 可以理解成:

text 复制代码
index.html = 房子的门

src = 房子里的东西

浏览器先通过门进来,再加载里面的应用。


4. main.ts 是干什么的?

main.ts 是 Vue 应用的:

JavaScript/TypeScript 启动入口。

典型代码:

ts 复制代码
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

只有三步。

第一步

ts 复制代码
import { createApp } from 'vue'

拿到 Vue 提供的创建应用函数。

第二步

ts 复制代码
import App from './App.vue'

拿到你的根组件。

第三步

ts 复制代码
createApp(App).mount('#app')

可以拆开:

ts 复制代码
const app = createApp(App)

app.mount('#app')

意思是:

text 复制代码
创建 Vue 应用
      ↓
根组件 = App.vue
      ↓
挂载到 index.html 的 #app

注意 index.html

html 复制代码
<div id="app"></div>

正好对应:

ts 复制代码
.mount('#app')

最终:

text 复制代码
index.html

<div id="app"></div>
      ↑
      │
main.ts
createApp(App).mount('#app')
             ↑
             │
           App.vue

这三个文件因此连起来了。


5. App.vuemain.ts 是什么关系?

这个问题面试也很容易被问。

准确说:

text 复制代码
main.ts
    ↓ 创建应用
App.vue
    ↓ 作为根组件
其他组件

例如:

ts 复制代码
// main.ts

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

这里:

ts 复制代码
App

就是:

text 复制代码
App.vue

因此:

main.ts 是程序启动入口,App.vue 是组件树的根节点。

假设:

vue 复制代码
<!-- App.vue -->

<script setup>
import Header from './components/Header.vue'
import TodoList from './components/TodoList.vue'
</script>

<template>
  <Header />

  <TodoList />
</template>

整个组件树就是:

text 复制代码
index.html

<div id="app">
     │
     ▼
   App.vue
    /   \
Header TodoList
          │
          ▼
       TodoItem

所以不要把它们混为一谈。

text 复制代码
main.ts
职责:启动 Vue

App.vue
职责:描述 UI

可以类比:

text 复制代码
main.ts = 点火开关

App.vue = 整辆车

6. 浏览器为什么能识别 .vue 文件?

这里有一个很重要的认知:

浏览器其实不认识 .vue 文件。

来源 浏览器原生认识的主要是:

text 复制代码
HTML
CSS
JavaScript

浏览器并不知道:

vue 复制代码
<script setup>
const message = 'hello'
</script>

<template>
  <h1>{{ message }}</h1>
</template>

<style>
h1 {
  color: red;
}
</style>

是什么意思。

所以:

ts 复制代码
import App from './App.vue'

直接扔给普通浏览器是不行的。


真正处理它的是:

text 复制代码
Vite
+
@vitejs/plugin-vue
+
@vue/compiler-sfc

.vue 叫:

SFC ------ Single File Component,单文件组件。

例如:

vue 复制代码
<script setup>
const count = 1
</script>

<template>
  <div>{{ count }}</div>
</template>

<style>
div {
  color: red;
}
</style>

Vite 遇到:

ts 复制代码
import App from './App.vue'

后,大致会经过:

text 复制代码
App.vue
   ↓
@vitejs/plugin-vue
   ↓
@vue/compiler-sfc
   ↓

<script>
    ↓
JavaScript

<template>
    ↓
render 函数

<style>
    ↓
CSS

例如:

vue 复制代码
<template>
  <h1>Hello</h1>
</template>

会被编译成类似:

js 复制代码
function render() {
  return createElementVNode(
    "h1",
    null,
    "Hello"
  )
}

最后浏览器真正执行的是:

text 复制代码
JavaScript
+
CSS

而不是 .vue

因此完整链路是:

text 复制代码
浏览器
   │
   ▼
index.html
   │
   ▼
/src/main.ts
   │
   ▼
import App.vue
   │
   │ 浏览器请求 App.vue
   ▼
Vite Dev Server
   │
   ▼
Vue Plugin
   │
   ▼
Vue Compiler
   │
   ▼
JavaScript
   │
   ▼
浏览器执行

最后把 6 个知识点串起来

这是你现在最应该形成的工程心智模型:

text 复制代码
                package.json
              项目依赖 / 命令
                    │
                    ▼
              npm run dev
                    │
                    ▼
                  Vite
                    │
            vite.config.ts
            配置 Vite 行为
                    │
                    ▼
               index.html
                    │
          <script src="/src/main.ts">
                    │
                    ▼
                 main.ts
                    │
          createApp(App)
                    │
                    ▼
                 App.vue
                    │
              其他 Vue 组件

其中 .vue 文件:

text 复制代码
.vue
 ↓
Vite + Vue Plugin
 ↓
Vue Compiler
 ↓
JavaScript + CSS
 ↓
浏览器

所以你可以用一句话概括整个 Vue 项目启动过程:

推导 浏览器首先加载根目录的 index.htmlindex.html 通过 ES Module 引入 main.tsmain.ts 使用 createApp 创建 Vue 应用,以 App.vue 作为根组件并挂载到 #app。开发过程中 Vite 根据 vite.config.ts 处理模块请求,并通过 Vue 插件把浏览器无法直接执行的 .vue SFC 编译成 JavaScript 和 CSS。

相关推荐
前端·柱子1 小时前
Chaikin‘s Corner Cutting 算法 应用canvas绘制平滑的曲线
前端·html
爱丶不疚1 小时前
Electron: 缓存机制有哪些?能控制的又有哪些
前端·electron·v8
计算机魔术师1 小时前
一边喊安全一边烧钱竞赛:AI「减速」倡议背后的两副面孔
前端
右耳朵猫AI1 小时前
Web前端周刊2026W37 | Shopify 转原生、React 编译 Rust 化、Vitest 5.0、Rslib 1.0
前端·javascript·react.js·typescript·node.js
涛涛ing1 小时前
2026年,这5个JS新趋势正在悄悄改写前端
前端
郝学胜-神的一滴1 小时前
C++20模板元编程 02:吃透模板基础核心四大核心知识点
开发语言·数据结构·c++·程序人生·软件工程·visual studio
moonsims1 小时前
AiBrainBox-UGV 的目标跟踪从“传统视觉跟踪”升级为“语义目标跟踪”
前端·人工智能·量子计算
驭渊的小故事1 小时前
Spring Boot 注解详解01
java·前端·spring boot
pe7er2 小时前
引子
前端·后端·架构