docs(frontend-engineering): enhance build pipeline demo and documentation

This commit is contained in:
sanbuphy
2026-02-13 01:36:09 +08:00
parent 0d12dacf8c
commit 599052b2e0
2 changed files with 476 additions and 74 deletions
@@ -6,32 +6,103 @@
<span class="subtitle">从源代码到产物的完整旅程</span>
</div>
<div class="intro-text">
想象你在开一家<span class="highlight">面包店</span>面粉要过筛搅拌发酵烘烤最后才能变成香喷喷的面包代码也一样需要经过一道道"加工工序"才能变成浏览器能运行的程序
</div>
<div class="pipeline">
<div v-for="(stage, i) in stages" :key="stage.id" class="stage">
<div
v-for="(stage, i) in stages"
:key="stage.id"
class="stage"
:class="{ active: activeStage === stage.id }"
@click="activeStage = activeStage === stage.id ? null : stage.id"
>
<div class="stage-icon">{{ stage.icon }}</div>
<div class="stage-name">{{ stage.name }}</div>
<div class="stage-desc">{{ stage.desc }}</div>
<div class="stage-simple">{{ stage.simple }}</div>
<div v-if="i < stages.length - 1" class="arrow"></div>
</div>
</div>
<Transition name="fade">
<div v-if="activeStage" class="stage-detail">
<div class="detail-header">
<span class="detail-icon">{{ currentStage?.icon }}</span>
<span class="detail-title">{{ currentStage?.name }}</span>
</div>
<div class="detail-content">
<p class="detail-desc">{{ currentStage?.detailDesc }}</p>
<div class="detail-example">
<div class="example-label">🌰 举个例子</div>
<div class="example-content">{{ currentStage?.example }}</div>
</div>
</div>
</div>
</Transition>
<div v-if="!activeStage" class="hint-text">
👆 点击上方任意阶段查看详细解释
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>流水线思想</strong>就像工厂流水线一样代码经过一道道工序最终变成可以在浏览器运行的产物每个阶段各司其职环环相扣
<strong>核心思想</strong>就像工厂流水线一样代码经过一道道工序最终变成可以在浏览器运行的产物每个阶段各司其职环环相扣
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed } from 'vue'
const activeStage = ref(null)
const stages = ref([
{ id: 1, icon: '🔍', name: '代码检查', desc: 'ESLint/TSC' },
{ id: 2, icon: '⚙️', name: '代码转换', desc: 'Babel/SWC' },
{ id: 3, icon: '📦', name: '依赖解析', desc: '构建依赖图' },
{ id: 4, icon: '📚', name: '模块打包', desc: 'Webpack/Rollup' },
{ id: 5, icon: '', name: '代码优化', desc: '压缩/TreeShake' }
{
id: 1,
icon: '🔍',
name: '代码检查',
simple: '找错误',
detailDesc: '就像写作文前先检查有没有错别字和语法错误。代码检查工具会自动发现你的代码问题,比如变量名拼写错误、漏写了分号、使用了未定义的变量等。',
example: '你写了 const mesage = "hello",检查工具会提醒:"mesage 是不是想写 message?这个变量名看起来有拼写错误。"'
},
{
id: 2,
icon: '⚙️',
name: '代码转换',
simple: '翻译官',
detailDesc: '就像把中文翻译成英文让外国人能看懂。你写的可能是 TypeScript 或新版 JavaScript 语法,但老浏览器"看不懂",需要转换成它们能理解的旧版本。',
example: '你写了 const name = user?.name(新版语法),转换后变成 var name = user && user.name ? user.name : undefined(老浏览器能懂的写法)'
},
{
id: 3,
icon: '📦',
name: '依赖解析',
simple: '理关系',
detailDesc: '就像整理食谱,搞清楚做一道菜需要哪些食材。你的代码可能引用了很多其他文件,这个阶段会分析"谁依赖谁",画出一张完整的关系图。',
example: 'main.js 引用了 utils.jsutils.js 又引用了 helper.js,解析后会生成一张"依赖地图",告诉打包工具按什么顺序处理这些文件。'
},
{
id: 4,
icon: '📚',
name: '模块打包',
simple: '装箱子',
detailDesc: '就像搬家时把零散的东西装进几个大箱子。你的项目可能有上百个文件,浏览器加载太多小文件会很慢,打包就是把它们合并成少数几个文件。',
example: '原来有 100 个 .js 文件,打包后变成 2 个文件:app.js(你的代码)和 vendor.js(第三方库)。浏览器只需请求 2 次而不是 100 次。'
},
{
id: 5,
icon: '✨',
name: '代码优化',
simple: '瘦身',
detailDesc: '就像压缩行李箱,把不必要的东西扔掉。删除代码中的空格和注释、去掉没用到代码(Tree Shaking)、压缩变量名,让文件体积更小。',
example: '原来 100KB 的代码,优化后变成 30KB。比如把 function getUserName() { return name } 压缩成 function a(){return n}'
}
])
const currentStage = computed(() => {
return stages.value.find(s => s.id === activeStage.value)
})
</script>
<style scoped>
@@ -47,13 +118,28 @@ const stages = ref([
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 1rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.pipeline {
display: flex;
align-items: flex-start;
@@ -68,8 +154,20 @@ const stages = ref([
display: flex;
flex-direction: column;
align-items: center;
min-width: 80px;
min-width: 85px;
position: relative;
cursor: pointer;
padding: 0.5rem;
border-radius: 8px;
transition: all 0.2s ease;
}
.stage:hover {
background: var(--vp-c-bg-soft);
}
.stage.active {
background: var(--vp-c-brand-soft);
}
.stage-icon {
@@ -82,6 +180,11 @@ const stages = ref([
justify-content: center;
font-size: 1.25rem;
margin-bottom: 0.5rem;
transition: transform 0.2s ease;
}
.stage:hover .stage-icon {
transform: scale(1.1);
}
.stage-name {
@@ -90,20 +193,91 @@ const stages = ref([
color: var(--vp-c-text-1);
}
.stage-desc {
.stage-simple {
font-size: 0.7rem;
color: var(--vp-c-text-3);
color: var(--vp-c-brand-1);
margin-top: 0.2rem;
font-weight: 500;
}
.arrow {
position: absolute;
right: -12px;
top: 16px;
top: 20px;
color: var(--vp-c-text-3);
font-size: 1rem;
}
.hint-text {
text-align: center;
font-size: 0.85rem;
color: var(--vp-c-text-3);
margin-top: 0.75rem;
}
.stage-detail {
background: var(--vp-c-bg);
border-radius: 8px;
padding: 1rem;
margin-top: 0.75rem;
border: 1px solid var(--vp-c-divider);
}
.detail-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.detail-icon {
font-size: 1.5rem;
}
.detail-title {
font-weight: 600;
font-size: 1rem;
color: var(--vp-c-text-1);
}
.detail-desc {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 0.75rem;
}
.detail-example {
background: var(--vp-c-bg-soft);
padding: 0.75rem;
border-radius: 6px;
border-left: 3px solid var(--vp-c-brand);
}
.example-label {
font-size: 0.8rem;
font-weight: 500;
color: var(--vp-c-text-2);
margin-bottom: 0.5rem;
}
.example-content {
font-size: 0.85rem;
color: var(--vp-c-text-1);
line-height: 1.5;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease, transform 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(-10px);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
+288 -60
View File
@@ -63,7 +63,19 @@
## 2. 核心概念:转译、打包、构建
在深入学习具体工具之前,我们需要先搞清楚几个经常被混淆的核心概念:转译、打包和构建。这三个词听起来很像,但实际上各有不同的含义和职责。为了帮助你更好地理解,我们用一个餐厅的比喻来类比它们之间的关系
::: tip 🤔 这些概念和构建有什么关系
转译、打包就是流水线上的关键工序。
当你运行 `npm run build` 时,构建工具会依次执行:
1. **代码检查** → 发现错误
2. **转译** → 把新语法翻译成浏览器能懂的代码
3. **打包** → 把分散的文件合并起来
4. **优化** → 压缩体积、删除无用代码
所以,**转译和打包是构建流程的核心环节**。理解它们,你才能知道构建工具到底在做什么,为什么有时候构建很慢,为什么有时候打包后体积很大。
:::
在深入学习具体工具之前,我们需要先搞清楚这几个核心概念。为了帮助你更好地理解,我们用一个餐厅的比喻来类比它们之间的关系。
### 2.1 用餐厅比喻理解三个概念
@@ -71,9 +83,9 @@
| 概念 | 🍽️ 餐厅比喻 | 实际作用 | 具体例子 |
|------|-------------|----------|----------|
| **转译** | 把中文菜谱翻译成英文,让外国厨师也能看懂 | 把新语法转换成浏览器能理解的旧语法 | ES2022 → ES5、TypeScript → JavaScript |
| **打包** | 把各桌点的菜装成一个个外卖盒,方便配送 | 把分散的模块文件合并成少数几个文件 | 100 个源文件 → 3 个 bundle 文件 |
| **构建** | 从接单、做菜、打包到配送的完整流程 | 从源代码到生产代码的完整转换过程 | 编译、检查、打包、优化、输出 |
| **转译** | 把中文菜谱翻译成英文,让外国厨师也能看懂 | 把新语法转换成浏览器能理解的旧语法 | 你写 `const name = user?.name`,转译后变成 `var name = user && user.name` |
| **打包** | 把各桌点的菜装成一个个外卖盒,方便配送 | 把分散的模块文件合并成少数几个文件 | 你写了 50 个 .js 文件,打包后变成 2 个文件 |
| **构建** | 从接单、做菜、打包到配送的完整流程 | 从源代码到生产代码的完整转换过程 | 执行 `npm run build` 后,src 文件夹变成 dist 文件夹 |
### 2.2 转译(Transpile):代码的"翻译官"
@@ -114,6 +126,21 @@ var result =
- **SWC** 是用 Rust 语言重写的转译器,速度比 Babel 快 20 倍以上,正在被越来越多的项目采用,包括 Next.js 等知名框架。
- **esbuild** 是用 Go 语言编写的,同样以速度著称,Vite 在开发模式下就使用它来进行快速转译。
::: details 🔍 我的项目用的是什么转译工具?
你不需要刻意选择,通常是由项目脚手架决定的:
| 项目类型 | 默认转译工具 |
|---------|-------------|
| Vite 项目 | esbuild(开发模式)+ esbuild/rollup(生产模式) |
| Create React App | Babel |
| Next.js | SWC(新版本)/ Babel(旧版本) |
| Vue CLI | Babel |
想知道自己项目用的是什么?打开 `package.json`,搜索 `babel``@babel/core` 这些关键词。如果找到了,说明用的是 Babel;如果没有,很可能是 esbuild 或 SWC。
**其实你不需要关心这个**——这些工具对开发者是"透明"的,你只管写代码,它们会在后台默默工作。
:::
### 2.3 打包(Bundle):模块的"打包员"
打包是指把多个分散的模块文件合并成一个(或几个)文件的过程。在早期的前端开发中,我们习惯把所有代码写在一个 JS 文件里,但随着项目规模增大,这种方式变得难以维护。现代前端采用模块化开发,每个功能一个文件,但浏览器加载大量小文件会带来性能问题,这就需要打包工具来帮忙。
@@ -202,23 +229,79 @@ dist/
## 3. 实战:一个团队的工程化演进之路
讲了这么多概念,让我们看一个真实的案例:某创业公司是如何从"直接写 HTML"一步步进化到"现代化工程化流程"的。这个案例中的很多问题和解决方案,可能正是你目前面临或将要面临的。
::: tip 🤔 什么是"工程化"
说了半天"工程化",它到底是什么意思?
**简单来说,工程化就是把"手工作坊"变成"现代化工厂"的过程。**
想象一下:你在家做饭,想吃什么就做什么,很自由。但如果要开一家餐厅,每天服务几百个顾客,就不能再"想做什么做什么"了——你需要标准化的菜谱、规范的操作流程、统一的原材料采购,这样才能保证每道菜的质量稳定、出餐效率高。
前端开发也一样。一个人写小项目,怎么写都行。但团队协作、项目变大后,就需要:
- **统一的代码规范**:大家都按同样的方式写代码
- **自动化工具**:让机器帮我们检查错误、转换代码、打包文件
- **标准化流程**:从开发到上线有一套清晰的步骤
**这就是工程化:用工具和规范,让开发更高效、代码更可靠、协作更顺畅。**
:::
讲了这么多概念,让我们看一个真实的案例:某创业公司是如何从"直接写 HTML"一步步进化到"现代化工程化流程"的。通过这个案例,你会更直观地理解工程化到底解决了什么问题。
::: tip 📖 背景知识:jQuery、Vue、React 是什么?
在开始案例之前,先简单介绍一下这些名词:
- **jQuery**:十多年前最流行的 JavaScript 库,用来简化 DOM 操作(比如"点击按钮后改变文字")。现在已经被 Vue、React 等现代框架取代,但很多老项目还在用。
- **Vue / React**:现代前端开发的主流框架。它们让你用"组件"的方式组织代码,数据和视图自动同步,开发效率更高。你现在学的很可能就是其中之一。
**简单理解**jQuery 是"手动挡",你要自己操作每一个元素;Vue/React 是"自动挡",你只需要告诉它数据是什么,它会自动更新界面。
:::
### 3.1 演进的全景图
| 阶段 | 时代背景 | 主要特征 | 核心痛点 |
|------|----------|----------|----------|
| **阶段一:原始时代** | 早期小团队 | 直接写 HTML/JS/CSS | 全局变量污染、依赖混乱 |
| **阶段二:模块化** | 团队扩张期 | 引入 Webpack + Babel | 构建速度慢、配置复杂 |
| **阶段三:现代化** | 追求效率期 | 迁移到 Vite | 需要学习新工具链 |
| **阶段四:持续优化** | 成熟稳定期 | 不断改进和优化 | 避免常见的打包陷阱 |
::: tip 🤔 什么是脚手架?
脚手架就是帮你"搭好项目骨架"的工具。比如 `npm create vite@latest` 会自动创建一个配置好的项目,里面有目录结构、配置文件、示例代码,你直接开始写业务代码就行。
### 3.2 阶段一:原始时代——痛点初现
**没有脚手架的时代**:你要手动创建文件夹、写配置文件、安装依赖...一个项目搭建下来可能要半天。
**有脚手架的时代**:一条命令,30 秒搞定。
:::
在这个阶段,团队只有 3 个前端工程师,做一个管理后台项目。当时的项目结构非常简单:几个 HTML 页面,加上一些 CSS 和 JS 文件,以及一些图片资源。
下面这张表展示了工程化演进的四个阶段,你可以看到构建工具、脚手架、框架是如何一步步进化的:
| 阶段 | 构建工具 | 脚手架 | 框架 | 核心变化 |
|------|---------|--------|------|----------|
| **阶段一:原始时代** | 无(直接运行) | 无(手动建文件) | jQuery | 没有任何工具,全靠手工 |
| **阶段二:模块化** | Webpack + Babel | 简单模板复制 | Vue 2 / React | 开始有构建流程,但配置很麻烦 |
| **阶段三:现代化** | Vite | create-vite / create-react-app | Vue 3 / React 18 | 开箱即用,零配置启动 |
| **阶段四:持续优化** | Vite + 插件 | 自定义脚手架模板 | 框架 + TypeScript | 团队规范化、模板化 |
::: tip 📊 从表格中你能看到什么?
让我们逐行解读这张表:
**阶段一 → 阶段二**:从"没有工具"到"有了工具"。这是质的飞跃——你开始用构建工具处理代码,用框架组织项目。但代价是配置复杂,新人上手难。
**阶段二 → 阶段三**:从"能用"到"好用"。Vite 把原来需要手动配置的东西都自动化了,脚手架一键生成项目,开发体验大幅提升。你现在大概率就处在这个阶段。
**阶段三 → 阶段四**:从"个人好用"到"团队高效"。当团队变大后,需要统一的技术栈和规范,这时候会自定义脚手架模板,让所有项目保持一致的风格。
**总结一下**:工程化演进不只是"构建工具变快了",而是**整个开发体验的升级**——从手动搭建项目到脚手架一键生成,从复杂配置到开箱即用,从各自为战到团队规范。
:::
### 3.2 阶段一:原始时代——全靠手工
为什么叫"原始时代"?因为这个阶段没有任何自动化工具,所有事情都要手动完成——创建文件夹、写代码、管理依赖、调试问题,全部靠人工。
在这个阶段,团队只有 3 个前端工程师,做一个管理后台项目。项目很小,大家各写各的,看起来没什么问题。但随着项目变大,问题开始暴露出来。
**开发方式**
- **构建工具**:无,直接写 HTML/JS/CSS,浏览器直接运行
- **脚手架**:无,手动创建文件夹和文件
- **框架**jQuery,用选择器操作 DOM
**这个阶段的特点**
-**优点**:简单直接,没有学习成本,写完就能跑
-**缺点**:代码一多就乱,团队协作困难,没有代码检查容易出 bug
::: details 查看当时的项目结构和代码方式
**项目结构**
**项目结构**(手动创建)
```
project/
├── index.html
@@ -266,47 +349,72 @@ var ModuleA = (function () {
这种开发方式在小项目中还能应付,但随着团队扩大到 8 人、项目变得越来越复杂,这些问题开始严重影响开发效率和代码质量,团队迫切需要一种更好的组织方式。
### 3.3 阶段二:引入模块化——初见曙光
### 3.3 阶段二:模块化时代——开始有工具链
转折点出现在团队决定引入现代化工具链。他们选择了 Webpack 作为打包工具,Babel 作为转译器,ESLint 作为代码检查工具,并用 npm/yarn 管理依赖。这次升级带来了质的飞跃
原始时代的问题积累到一定程度,团队终于决定引入现代化工具链。这是一个重要的转折点——从"手工劳动"进入"机械化生产"
::: details 查看引入 Webpack 后的变化
**新的项目结构**(模块化组织):
但这个阶段也有代价:工具链的学习成本很高,配置文件复杂,新人上手需要时间。
**开发方式**
- **构建工具**Webpack + Babel,需要写配置文件
- **脚手架**:复制旧项目模板,手动改配置
- **框架**Vue 2 / React,组件化开发
**这个阶段的特点**
-**优点**:模块化开发,代码可维护性大幅提升,有代码检查
-**缺点**:配置复杂,启动慢,脚手架简陋容易出错
::: details 查看引入工具链后的变化
**项目结构**Webpack + Vue 2 时代):
```
src/
├── components/ # 可复用的 UI 组件
│ ├── Button/
│ ├── index.js
│ ├── Button.vue
│ │ └── Button.test.js
│ └── Modal/
├── utils/ # 工具函数
my-project/
├── build/ # 构建配置(这个阶段配置很复杂!)
│ ├── webpack.base.js
│ ├── webpack.dev.js
└── webpack.prod.js
├── config/ # 环境配置
│ ├── index.js
│ ├── date.js
│ └── http.js
├── services/ # API 服务层
│ ├── user.js
── order.js
├── assets/ # 静态资源
│ ├── images/
── styles/
├── App.vue # 根组件
── main.js # 入口文件
│ ├── dev.env.js
│ └── prod.env.js
├── src/
│ ├── components/ # 组件
── views/ # 页面
│ ├── router/ # 路由
│ ├── store/ # 状态管理
── App.vue
│ └── main.js
── static/ # 静态资源
├── .eslintrc.js # ESLint 配置
├── .babelrc # Babel 配置
├── package.json
└── index.html
```
**现代化代码示例**
**配置文件示例**(这就是为什么说"配置复杂")
```js
// ES6 模块化导入,依赖关系清晰
import { debounce } from 'lodash-es'
import Button from '@/components/Button.vue'
// webpack.base.js - 仅仅是基础配置就有这么多内容
const path = require('path')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
export default {
components: { Button },
methods: {
// 使用 debounce 防抖,代码简洁优雅
handleInput: debounce(function() {
// 处理输入逻辑
}, 300)
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].[contenthash].js'
},
module: {
rules: [
{ test: /\.vue$/, loader: 'vue-loader' },
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
{ test: /\.(png|jpg|gif)$/, loader: 'url-loader', options: { limit: 8192 } }
]
},
plugins: [new VueLoaderPlugin()],
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: { '@': path.resolve(__dirname, '../src') }
}
}
```
@@ -316,31 +424,81 @@ export default {
2. **代码复用**:组件和工具函数可以在不同项目中复用,不用再复制粘贴
3. **代码质量**:ESLint 在保存时自动检查,TypeScript 在编译时发现类型错误
4. **性能优化**:Webpack 的代码分割和懒加载让首屏加载速度大幅提升
**新的痛点**
1. **配置复杂**webpack.config.js 动辄几百行,新人很难上手
2. **启动慢**:冷启动 30 秒以上,改代码热更新要等 5 秒
3. **脚手架简陋**:复制旧项目模板,经常忘记改配置,导致各种奇怪问题
:::
然而,随着项目规模继续增长,Webpack 的问题也开始显现:冷启动时间越来越长,大型项目的冷启动可能需要 30 秒以上;修改代码后的热更新也需要等待好几秒;复杂的配置文件动辄几百行,新人很难快速上手。
### 3.4 阶段三:现代化时代——开箱即用
### 3.4 阶段三:迁移到 Vite——效率飞跃
阶段二的痛点(配置复杂、启动慢)困扰了开发者很多年。直到 2021 年,Vite 的出现彻底改变了这一切。
Vite 的核心理念是"约定优于配置"——它内置了合理的默认配置,你不需要写几百行配置文件,开箱即用。这就像从"自己组装电脑"变成了"买品牌机",省去了大量折腾的时间。
2021 年之后,团队开始用 Vite 替代 Webpack,开发体验得到了质的提升。
::: details Vite 与 Webpack 的对比
| 对比项 | Webpack | Vite | 差异 |
**开发方式**
- **构建工具**:Vite,零配置启动,秒级热更新
- **脚手架**`npm create vite@latest`,一键生成项目
- **框架**Vue 3 / React 18,更强大的组件系统
**这个阶段的特点**
-**优点**:秒级启动,热更新极快,配置简单,新人友好
-**缺点**:生态还在完善中,某些特殊需求可能需要额外配置
::: details Vite 带来的变化
**项目结构**Vite + Vue 3 时代):
```
my-project/
├── src/
│ ├── components/ # 组件
│ ├── views/ # 页面
│ ├── router/ # 路由
│ ├── stores/ # 状态管理(Pinia
│ ├── assets/ # 静态资源
│ ├── App.vue
│ └── main.js
├── public/ # 公共资源
├── vite.config.js # 配置文件(简洁!)
├── package.json
└── index.html
```
**配置文件对比**Vite 配置有多简洁):
```js
// vite.config.js - 整个配置文件就这么点
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: { '@': '/src' }
}
})
// 对比上面 Webpack 的配置,是不是简洁太多了?
```
| 对比项 | 阶段二(Webpack) | 阶段三(Vite | 体验提升 |
|--------|---------|------|------|
| 冷启动 | 30s+ | <1s | **快 30 倍以上** |
| HMR 更新 | 3-5s | <100ms | **快 30 倍以上** |
| 配置复杂度 | 高(需大量配置) | 低(约定优于配置) | **大幅简化** |
| 学习曲线 | 陡峭 | 平缓 | **更容易上手** |
| 创建项目 | 复制模板,手动改配置 | `npm create vite@latest` | 30 秒搞定 |
| 冷启动 | 30s+ | <1s | **快 30 倍** |
| 热更新 | 3-5s | <100ms | **快 30 倍** |
| 配置文件 | 几百行 | 几十行甚至不需要 | **大幅简化** |
**实际体验对比**
```bash
# 以前使用 Webpack
# 阶段二:使用 Webpack
npm run dev
# 等待 30 秒...喝杯咖啡回来还在编译
# [INFO] Compiled successfully in 30123ms
# 修改代码 -> 保存 -> 等待 5 秒 -> 终于看到效果
# 现在使用 Vite
# 阶段三:使用 Vite
npm create vite@latest my-project # 一键创建项目
cd my-project && npm install
npm run dev
# 等待 300 毫秒...还没反应过来就好了
# [INFO] ready in 312ms
@@ -348,11 +506,81 @@ npm run dev
```
:::
### 3.5 阶段四:持续优化——避坑指南
### 3.5 阶段四:持续优化——团队规范化
在工程化演进的过程中,团队也踩过不少坑。这些坑很多都与构建和打包有关,了解它们可以帮助你避免重蹈覆辙。
当工具链成熟后,团队开始关注更深层次的问题:如何让团队协作更高效?如何避免重复踩坑?如何统一代码风格?
::: details 常见踩坑与解决方案
这个阶段的核心是"规范化"——不只是工具好用,还要让团队所有人用同样的方式工作。
**开发方式**
- **构建工具**:Vite + 自定义插件,适配团队特殊需求
- **脚手架**:团队内部脚手架模板,统一技术栈和规范
- **框架**Vue 3 / React 18 + TypeScript,类型安全
**这个阶段的特点**
-**优点**:团队协作高效,代码风格统一,新人入职有模板可循
-**缺点**:需要投入时间维护脚手架和规范,有一定维护成本
**这个阶段会做什么?**
1. **自定义脚手架模板**:把团队常用的配置、目录结构、公共组件打包成模板,新项目一键生成
2. **引入 TypeScript**:让代码有类型检查,减少运行时错误
3. **建立代码规范**:ESLint 规则、Git 提交规范、代码审查流程
4. **持续集成/持续部署(CI/CD**:代码提交后自动测试、自动部署
::: details 团队规范化阶段的项目结构
**项目结构**(团队内部模板 + TypeScript):
```
my-project/
├── .husky/ # Git hooks(提交前自动检查)
├── src/
│ ├── components/ # 组件
│ ├── views/ # 页面
│ ├── router/ # 路由
│ ├── stores/ # 状态管理
│ ├── api/ # API 接口
│ ├── utils/ # 工具函数
│ ├── types/ # TypeScript 类型定义
│ ├── assets/ # 静态资源
│ ├── App.vue
│ └── main.ts # 注意是 .ts 不是 .js
├── public/
├── .eslintrc.cjs # ESLint 配置(团队统一规则)
├── .prettierrc # Prettier 配置(代码格式化)
├── tsconfig.json # TypeScript 配置
├── vite.config.ts # Vite 配置
├── package.json
└── README.md # 项目文档
```
**团队规范化的具体体现**
```js
// tsconfig.json - TypeScript 配置,类型安全
{
"compilerOptions": {
"target": "ES2020",
"strict": true, // 开启严格模式
"noImplicitAny": true, // 禁止隐式 any
"baseUrl": ".",
"paths": { "@/*": ["src/*"] }
}
}
// .eslintrc.cjs - 团队统一的代码规范
module.exports = {
extends: [
'plugin:vue/vue3-recommended',
'@vue/standard',
'@vue/typescript/recommended'
],
rules: {
'no-console': 'warn', // 禁止 console.log
'no-debugger': 'error', // 禁止 debugger
'vue/multi-word-component-names': 'error' // 组件名必须是多词
}
}
```
**常见踩坑与解决方案**
**坑一:引入整个库而不是按需引入**