傳統方式搭建前端專案:查文檔、試錯、調試,耗時 1 天起步。AI 輔助:對話式配置,1 小時搞定。這是《AI 編程實戰:TRAE SOLO 全棧開發指南》專欄的第二篇文章,帶你用 AI 快速搭建專業級前端專案架構。
還記得上一篇文章裡提到的小何嗎?他在"心動戀聊"專案中遇到的第一個挑戰,就是前端專案初始化。
如果你做過前端專案,一定深有體會:
技術選型迷茫:
UniApp vs Taro vs 原生?
Vue3 還是 React?
Vite 還是 Webpack?
UnoCSS 還是 Tailwind CSS?
每個選擇背後都是無數的文檔、博客、踩坑記錄。光是技術選型,就能讓人糾結半天。
配置地獄:
vite.config.ts
tsconfig.json
uno.config.ts
.eslintrc.js
.prettierrc
pages.json
manifest.json
...
每一個配置檔都有自己的語法、規則、坑點。配置完一個,還有下一個在等著你。
時間黑洞:
小何最初的估算:
| 任務 | 預計時間 |
|---|---|
| 技術調研 | 2 小時 |
| 專案創建 | 0.5 小時 |
| Vite 配置 | 1 小時 |
| TypeScript 配置 | 1 小時 |
| UI 框架整合 | 2 小時 |
| 自動導入配置 | 1 小時 |
| 路由配置 | 1 小時 |
| 環境變數配置 | 0.5 小時 |
| 代碼規範配置 | 2 小時 |
| 總計 | 11 小時 |
實際上,由於各種問題、版本衝突、配置不兼容,往往需要 1.5-2 天。
有了 TRAE SOLO,一切都不同了。
小何的實際體驗:
小何:幫我創建一個 UniApp + Vue3 + TypeScript 專案,
使用 Vite 構建,支持微信小程序、H5、App 三端,
整合 UnoCSS 和 UView Pro 組件庫
AI:好的,我來幫你搭建完整的專案架構:
✓ 分析需求,確定技術選型
✓ 創建 Monorepo 專案結構
✓ 配置 Vite 構建工具
✓ 整合 TypeScript 嚴格模式
✓ 配置 UnoCSS 原子化 CSS
✓ 整合 UView Pro 組件庫
✓ 設置自動導入
✓ 配置多環境變數
✓ 添加代碼規範工具
專案結構已生成,請查看...
一天的工作,不到一小時完成。 這就是 AI 輔助開發的魔力。
專案開始前,小何需要確定技術選型。傳統做法是搜索各種博客文章、技術對比,然後糾結半天。
TRAE SOLO 的做法:
小何:幫我對比 UniApp、Taro、原生小程序的優劣,
專案需求:社交類小程序,需要支持微信小程序、H5、App 三端
AI:(通過 MCP 實時查閱最新文檔)
分析結論:
1. UniApp 優勢:
- 一套代碼,支持微信/H5/App/鴻蒙等多端
- Vue3 技術棧,學習成本低
- 生態完善,組件庫豐富
- 文檔完善,社區活躍
2. Taro 優勢:
- React 技術棧友好
- 適合已有 React 經驗的團隊
3. 原生小程序:
- 性能最優
- 但只能在單一平台運行
推薦:UniApp + Vue3
理由:
1. 專案需要三端發布,UniApp 跨端能力最強
2. 社交類應用迭代快,UniApp 開發效率高
3. 後續還要擴展到鴻蒙、安卓、iOS,UniApp 支持最全
5 分鐘,得到了專業級的技術選型分析報告。
小何:UniApp 應該用 Vite 還是 Webpack?
AI:強烈推薦 Vite!
對比分析:
┌────────────┬────────────────┬────────────────┐
│ 維度 │ Vite │ Webpack │
├────────────┼────────────────┼────────────────┤
│ 冷啟動 │ 毫秒級 │ 秒級 │
│ 熱更新 │ 即時 │ 有延遲 │
│ 配置複雜度 │ 簡單 │ 複雜 │
│ 生態支持 │ 完善 │ 非常完善 │
│ 構建速度 │ 快 │ 較慢 │
└────────────┴────────────────┴────────────────┘
實測數據(心動戀聊專案):
- Vite 冷啟動:1.2 秒
- Webpack 冷啟動:8.5 秒
結論:Vite 開發體驗完勝,選它!
通過 AI 輔助分析,"心動戀聊"專案確定了以下技術棧:
前端技術棧:
├── 框架:UniApp + Vue 3.4.21
├── 構建工具:Vite 5.2.8
├── 語言:TypeScript 5.7
├── 狀態管理:Pinia 2.0.36 + 持久化
├── 原子化 CSS:UnoCSS 66.0
├── UI 組件庫:UView Pro
├── HTTP 請求:自定義封裝(基於 uni.request)
├── 列表優化:z-paging 2.8.7
└── 數據請求:@tanstack/vue-query
"心動戀聊"採用 Monorepo 架構,這是現代前端專案的最佳實踐。
提示詞:
幫我創建一個 Monorepo 專案結構,包含:
1. apps/unibest-mp - UniApp 小程序端
2. apps/xindong-server - Next.js 服務端
3. packages/shared-types - 共享類型定義
使用 pnpm 管理依賴,Turborepo 編排任務
AI 生成的專案結構:
xingdong/
├── apps/
│ ├── unibest-mp/ # UniApp 多端應用
│ │ ├── src/
│ │ │ ├── api/ # API 接口定義
│ │ │ ├── components/ # 公共組件
│ │ │ ├── composables/ # 組合式函數
│ │ │ ├── config/ # 配置檔
│ │ │ ├── hooks/ # 自定義 Hooks
│ │ │ ├── http/ # HTTP 請求封裝
│ │ │ ├── layouts/ # 布局組件
│ │ │ ├── pages/ # 頁面檔
│ │ │ ├── store/ # Pinia 狀態管理
│ │ │ ├── subPackages/ # 分包頁面
│ │ │ │ ├── agreement/ # 協議相關
│ │ │ │ ├── vip/ # 會員相關
│ │ │ │ └── planForm/ # 計劃表單
│ │ │ ├── tabbar/ # 底部導航
│ │ │ └── utils/ # 工具函數
│ │ ├── env/ # 環境變數
│ │ ├── vite.config.ts # Vite 配置
│ │ └── package.json
│ │
│ └── xingdong-server/ # Next.js 服務端
│ ├── src/
│ │ └── app/ # App Router
│ └── package.json
│
├── packages/
│ └── shared-types/ # 共享類型定義
│ ├── src/
│ │ └── index.ts
│ └── package.json
│
├── pnpm-workspace.yaml # pnpm 工作區配置
├── turbo.json # Turborepo 配置
└── package.json # 根配置
pnpm-workspace.yaml:
packages:
- apps/*
- packages/*
turbo.json:
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["apps/unibest-mp/dist/**", "apps/xingdong-server/.next/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
這個結構的好處:
Vite 配置是前端專案的核心。讓我們看看 AI 生成的實際配置:
提示詞:
幫我配置 UniApp 的 Vite 配置檔,需要:
1. 自動導入 Vue API
2. 自動導入 uni-app API
3. 自動導入自定義 hooks
4. 配置路徑別名
5. 支持多環境變數
6. 整合 UnoCSS
7. 配置分包優化
生成的 vite.config.ts(實際專案配置):
// vite.config.ts 核心配置片段
export default ({ command, mode }) => {
// ... 環境變數加載邏輯 ...
return defineConfig({
plugins: [
// 1. 頁面路由自動生成
UniPages({
exclude: ['**/components/**/**.*'],
subPackages: [
'src/subPackages/agreement',
'src/subPackages/vip',
'src/subPackages/planForm',
],
}),
// 2. 布局系統 & 平台適配
UniLayouts(),
UniPlatform(),
UniManifest(),
// 3. 修復 Vue 編譯問題(AI 自動生成的補丁)
{
name: 'fix-vite-plugin-vue',
configResolved(config) {
const plugin = config.plugins.find((p) => p.name === 'vite:vue');
if (plugin && plugin.api && plugin.api.options) {
plugin.api.options.devToolsEnabled = false;
}
},
},
// 4. UnoCSS 原子化 CSS
UnoCSS(),
// 5. 自動導入
AutoImport({
imports: ['vue', 'uni-app'],
dirs: ['src/hooks'],
vueTemplate: true,
}),
// ... 其他插件
Uni(),
],
// ...
});
};
這個配置包含了:
fix-vite-plugin-vue 插件來解決特定的編譯 Bug,這在傳統開發中可能要排查半天。提示詞:
幫我配置 TypeScript 嚴格模式,確保類型安全,支持 Vue3 和 uni-app
生成的配置:
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "preserve",
"jsxImportSource": "vue",
"paths": {
"@/*": ["./src/*"],
"@img/*": ["./src/static/images/*"]
},
"types": ["@dcloudio/types", "@uni-helper/uni-types", "miniprogram-api-typings"]
},
"include": ["src/**/*.ts", "src/**/*.vue"],
"exclude": ["node_modules", "dist"]
}
UnoCSS 是原子化 CSS 的最佳選擇,但在小程序環境中使用時,AI 一開始給出的配置並不完美。
第一次嘗試:
小何:配置 UnoCSS
AI:生成了標準的 Web 端配置(presetUno)。
結果:小程序端樣式完全不生效。
修正後的互動:
小何:這個配置在微信小程序裡不生效,請檢查是否需要專用預設?
AI:抱歉,你是對的。在 UniApp 中需要使用 `@uni-helper/unocss-preset-uni`。
我已更新配置:
最終生成的 uno.config.ts:
import { defineConfig, presetIcons } from 'unocss';
import { presetUni } from '@uni-helper/unocss-preset-uni';
export default defineConfig({
presets: [
// 使用 UniApp 專用預設,解決小程序兼容性問題
presetUni({
attributify: {
prefixedOnly: true, // 避免屬性衝突
},
}),
presetIcons({
scale: 1.2,
warn: true,
}),
],
theme: {
colors: {
// 使用 CSS 變數,支持動態換膚
primary: 'var(--wot-color-theme,#0957DE)',
},
},
});
這裡的重點是 presetUni 和 prefixedOnly,這是 AI 在被指出錯誤後迅速修正的關鍵點。
UnoCSS 的優勢:
<!-- 傳統 CSS 寫法 -->
<template>
<view class="container">
<text class="title">心動戀聊</text>
</view>
</template>
<style scoped>
.container {
display: flex;
justify-content: center;
align-items: center;
padding: 16px;
}
.title {
font-size: 24px;
font-weight: bold;
color: #ff6b9d;
}
</style>
<!-- UnoCSS 寫法 -->
<template>
<view class="flex-center p-4">
<text class="text-24px font-bold text-primary">心動戀聊</text>
</view>
</template>
代碼量減少 70%,開發效率大幅提升!
UView Pro 是 UniApp 最好用的組件庫之一。
提示詞:
幫我整合 UView Pro 組件庫,配置按需導入和主題定製
package.json 依賴:
{
"dependencies": {
"uview-pro": "^0.0.3"
}
}
組件使用示例:
<template>
<view class="page">
<!-- 導航欄 -->
<u-navbar title="心動戀聊" :placeholder="true" />
<!-- 表單 -->
<u-form ref="formRef" :model="formData" :rules="rules">
<u-form-item label="暱稱" prop="nickname">
<u-input v-model="formData.nickname" placeholder="請輸入暱稱" />
</u-form-item>
<u-form-item label="性別" prop="gender">
<u-radio-group v-model="formData.gender">
<u-radio label="男" :name="1" />
<u-radio label="女" :name="2" />
</u-radio-group>
</u-form-item>
</u-form>
<!-- 按鈕 -->
<u-button type="primary" @click="handleSubmit">提交</u-button>
<!-- 彈窗 -->
<u-popup v-model:show="showPopup" mode="bottom">
<view class="p-4">彈窗內容</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
const formRef = ref();
const showPopup = ref(false);
const formData = reactive({
nickname: '',
gender: 1,
});
const rules = {
nickname: [{ required: true, message: '請輸入暱稱' }],
gender: [{ required: true, message: '請選擇性別' }],
};
const handleSubmit = async () => {
const valid = await formRef.value.validate();
if (valid) {
// 提交邏輯
}
};
</script>
傳統寫法每個檔案都要導入:
// 傳統寫法
import { ref, reactive, computed, watch, onMounted } from 'vue';
const count = ref(0);
const state = reactive({ name: '' });
配置自動導入後:
// 自動導入後,直接使用
const count = ref(0);
const state = reactive({ name: '' });
const double = computed(() => count.value * 2);
onMounted(() => {
console.log('mounted');
});
AutoImport 配置:
AutoImport({
imports: ['vue', 'uni-app'],
dts: 'src/types/auto-import.d.ts',
dirs: ['src/hooks'],
vueTemplate: true,
});
這會自動生成類型聲明檔 src/types/auto-import.d.ts:
// Auto generated by unplugin-auto-import
export {};
declare global {
const computed: typeof import('vue')['computed'];
const onMounted: typeof import('vue')['onMounted'];
const onUnmounted: typeof import('vue')['onUnmounted'];
const reactive: typeof import('vue')['reactive'];
const ref: typeof import('vue')['ref'];
const watch: typeof import('vue')['watch'];
// uni-app APIs
const onLaunch: typeof import('uni-app')['onLaunch'];
const onShow: typeof import('uni-app')['onShow'];
const onHide: typeof import('uni-app')['onHide'];
// ... 更多
}
在 src/hooks/ 目錄下創建的 hooks 也會自動導入:
src/hooks/useRequest.ts:
import type { Ref } from 'vue';
interface UseRequestOptions<T> {
immediate?: boolean;
onSuccess?: (data: T) => void;
onError?: (error: Error) => void;
}
export function useRequest<T>(fn: () => Promise<T>, options: UseRequestOptions<T> = {}) {
const { immediate = false, onSuccess, onError } = options;
const data: Ref<T | null> = ref(null);
const loading = ref(false);
const error = ref<Error | null>(null);
const execute = async () => {
loading.value = true;
error.value = null;
try {
data.value = await fn();
onSuccess?.(data.value);
} catch (e) {
error.value = e as Error;
onError?.(error.value);
} finally {
loading.value = false;
}
};
if (immediate) {
execute();
}
return { data, loading, error, execute };
}
使用時無需導入:
<script setup lang="ts">
// 直接使用,無需 import
const { data, loading, execute } = useRequest(() => apiGetUserInfo(), { immediate: true });
</script>
配置 @uni-helper/vite-plugin-uni-components 後,組件也自動註冊:
Components({
extensions: ['vue'],
deep: true,
directoryAsNamespace: false,
dts: 'src/types/components.d.ts',
});
src/components/UserCard.vue:
<template>
<view class="user-card">
<image :src="user.avatar" class="avatar" />
<text class="name">{{ user.name }}</text>
</view>
</template>
<script setup lang="ts">
defineProps<{
user: {
avatar: string;
name: string;
};
}>();
</script>
使用時無需註冊:
<template>
<!-- 直接使用,無需 import 和 components 註冊 -->
<UserCard :user="userInfo" />
</template>
使用 @uni-helper/vite-plugin-uni-pages,頁面路由可以自動生成。
在頁面檔中配置路由:
<!-- src/pages/index/index.vue -->
<route lang="json">
{
"style": {
"navigationBarTitleText": "首頁"
}
}
</route>
<template>
<view class="page">
<!-- 頁面內容 -->
</view>
</template>
自動生成的 pages.json:
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首頁"
}
},
{
"path": "pages/my/my",
"style": {
"navigationBarTitleText": "我的"
}
}
],
"subPackages": [
{
"root": "subPackages/agreement",
"pages": [
{
"path": "privacy",
"style": { "navigationBarTitleText": "隱私協議" }
},
{
"path": "user-agreement",
"style": { "navigationBarTitleText": "用戶協議" }
}
]
},
{
"root": "subPackages/vip",
"pages": [
{
"path": "index",
"style": { "navigationBarTitleText": "會員中心" }
}
]
}
],
"tabBar": {
"color": "#999999",
"selectedColor": "#FF6B9D",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首頁",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "static/tabbar/my.png",
"selectedIconPath": "static/tabbar/my-active.png"
}
]
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "心動戀聊",
"navigationBarBackgroundColor": "#ffffff",
"backgroundColor": "#F5F5F5"
}
}
小程序有包體積限制(主包 2MB,總包 20MB),分包是必須的。
配置分包:
// vite.config.ts
UniPages({
exclude: ['**/components/**/**.*'],
dts: 'src/types/uni-pages.d.ts',
subPackages: [
'src/subPackages/agreement', // 協議相關頁面
'src/subPackages/vip', // 會員相關頁面
'src/subPackages/planForm', // 計劃表單頁面
],
});
分包優化插件:
// @uni-ku/bundle-optimizer 自動優化
Optimization({
enable: {
optimization: true, // 開啟優化
'async-import': true, // 異步導入
'async-component': true, // 異步組件
},
dts: {
base: 'src/types',
},
});
"心動戀聊"專案支持多環境、多專案配置:
目錄結構:
env/
├── .env # 基礎配置
├── .env.development # 開發環境
└── .env.production # 生產環境
.env.development:
# 基礎配置
VITE_APP_PORT=5173
VITE_APP_PUBLIC_BASE=/
# API 配置
VITE_SERVER_BASEURL=http://localhost:3000
VITE_APP_PROXY=true
# 業務配置
VITE_APP_SOURCE_ID=your_source_id
VITE_APP_CHANNEL_ID=weixin
在代碼中使用:
// 直接使用
const apiBaseUrl = import.meta.env.VITE_SERVER_BASEURL;
const sourceId = import.meta.env.VITE_APP_SOURCE_ID;
// 類型安全
interface ImportMetaEnv {
VITE_APP_PORT: string;
VITE_SERVER_BASEURL: string;
VITE_APP_SOURCE_ID: string;
VITE_APP_CHANNEL_ID: string;
VITE_APP_BRAND_KEY: string;
}
啟動命令:
{
"scripts": {
"dev:mp": "uni -p mp-weixin --mode development",
"build:mp": "uni build -p mp-weixin --mode production"
}
}
提示詞:
配置 ESLint,適合 Vue3 + TypeScript + UniApp 專案
使用 @uni-helper/eslint-config:
// eslint.config.js
import uniHelper from '@uni-helper/eslint-config';
export default uniHelper({
typescript: true,
vue: true,
unocss: true,
});
// .prettierrc
{
"printWidth": 100,
"singleQuote": true,
"trailingComma": "all",
"semi": true,
"tabWidth": 2,
"endOfLine": "lf"
}
// package.json
{
"lint-staged": {
"*": "eslint --fix"
}
}
"心動戀聊"的首頁並不是一個簡單的展示頁,它包含了一個複雜的交互邏輯:文字/圖片輸入模式切換。
小何:首页需要一個輸入區域,支持兩種模式:
1. 文字模式:輸入對方說的話。
2. 圖片模式:上傳聊天截圖。
切換模式時,輸入框和上傳區域要互斥顯示。
並且需要一個"清除記憶"的功能,但只在文字模式下顯示。
這是一個涉及狀態管理、UI 交互和業務邏輯的複雜需求。AI 是如何一步步實現的呢?
第一步:定義狀態
AI 首先定義了核心的響應式狀態:
// src/pages/index/index.vue
const showUploadArea = ref(false); // 控制模式切換
const inputText = ref(''); // 文字輸入
const selectedImages = ref([]); // 圖片列表
// 切換模式邏輯
const toggleInputMode = () => {
showUploadArea.value = !showUploadArea.value;
// 切換時清空狀態,避免數據混淆
if (showUploadArea.value) {
inputText.value = '';
} else {
selectedImages.value = [];
}
};
第二步:構建動態 UI
利用 Vue 的 v-if/v-show 指令處理複雜的顯示邏輯:
<template>
<!-- 模式切換按鈕 -->
<view class="flex justify-between items-center">
<text>{{ showUploadArea ? '與Ta的聊天截圖:' : 'Ta說:' }}</text>
<view @click="toggleInputMode">
<text>{{ showUploadArea ? '切換文字' : '切換圖片' }}</text>
</view>
</view>
<!-- 上傳區域 (圖片模式) -->
<view v-show="showUploadArea" class="upload-area">
<ImageGrid :images="selectedImages" @add="addImages" />
</view>
<!-- 輸入框 (文字模式) -->
<view v-show="!showUploadArea" class="input-wrapper">
<u-input type="textarea" v-model="inputText" :autoHeight="true" />
</view>
<!-- 清除記憶 (僅文字模式) -->
<view v-if="!showUploadArea" class="clear-memory-btn" @click="handleClearMemory">
<text>清除記憶</text>
</view>
</template>
第三步:處理業務邏輯
生成回覆時,需要根據當前模式調用不同的接口:
const handleGenerate = async () => {
// 1. 鑑權檢查
if (!(await checkAuth())) return;
// 2. 模式判斷
if (showUploadArea.value) {
// 圖片模式邏輯
if (selectedImages.value.length === 0) return toast.info('請上傳截圖');
await generateByImage(selectedImages.value);
} else {
// 文字模式邏輯
if (!inputText.value.trim()) return toast.info('請輸入內容');
// 調用帶記憶的接口
await generateByText({
text: inputText.value,
sessionId: chatSessionStore.sessionId,
});
}
};
最終生成的代碼不僅邏輯清晰,還處理了很多細節,比如 iOS 的樣式適配:
// 適配 iOS 的輸入框樣式
const inputCustomStyle = computed(() => {
const isIOS = systemInfo?.platform === 'ios';
return {
padding: isIOS ? '12rpx' : '20rpx',
minHeight: '240rpx',
borderRadius: '12px',
};
});
這就是 AI 輔助開發的威力:它不僅能寫出跑通的代碼,還能考慮到平台差異和邊界情況。
# 微信小程序
pnpm --filter unibest-mp dev:mp
# H5
pnpm --filter unibest-mp dev:h5
# App
pnpm --filter unibest-mp dev:app
通過 AI 輔助,我們在 不到 1 小時 內完成了:
| 任務 | 完成情況 |
|---|---|
| ✅ Monorepo 專案結構 | 標準的 pnpm + Turborepo 架構 |
| ✅ Vite 配置 | 完整的插件鏈和優化配置 |
| ✅ TypeScript 配置 | 嚴格模式,完整類型支持 |
| ✅ UnoCSS 整合 | 原子化 CSS,主題定製 |
| ✅ UView Pro 整合 | 組件庫完整接入 |
| ✅ 自動導入配置 | Vue API、uni-app API、Hooks |
| ✅ 路由系統 | 自動生成,分包優化 |
| ✅ 環境變數 | 多環境、多專案支持 |
| ✅ 代碼規範 | ESLint + Prettier |
| ✅ 首頁開發 | 完整的頁面實現 |
專案初始化:
創建 [框架] + [技術棧] 專案,
包含 [目錄結構],
配置 [構建工具]
配置檔生成:
配置 [工具名稱],需要:
1. [功能點 1]
2. [功能點 2]
3. [功能點 3]
頁面生成:
創建 [頁面名稱],包括:
- [功能描述]
使用 [UI 框架] 和 [樣式方案]
《【AI 編程實戰】第 3 篇:AI 輔助後端開發 - Next.js 15 API 快速搭建》
我們將學習:
關注我,不錯過每一篇實戰乾貨!
如果這篇文章對你有幫助,請點讚、收藏、轉發,讓更多人了解 AI 編程的強大!
有任何問題,歡迎在評論區留言,我們一起討論。