系列文章: 前端工程師的 Modern Web 實踐之道 - Day 2
預計閱讀時間: 15 分鐘
難度等級: ⭐⭐⭐☆☆
在 Day 1 中,我們建立了 Modern Web 的核心理念:以 Developer Experience 和 User Experience 為中心的技術哲學。今天我們要將理論轉化為實際行動,解決每個前端工程師職涯中的第一個重大技術挑戰:如何構建一個既高效又具備前瞻性的開發環境?
還記得我在 2018 年從 PHP 轉向前端時的慘痛經歷嗎?光是讓一個簡單的 React 專案跑起來,就花了我整整三天時間:
# 2018年的設定噩夢
$ create-react-app my-app
$ cd my-app
$ npm start
# 第一天:node-sass 編譯失敗
Error: Node Sass does not yet support your current environment
# 第二天:babel 設定衝突
Module build failed: Error: Cannot find module '@babel/core'
# 第三天:webpack 版本不相容
TypeError: Cannot read property 'tap' of undefined
那種無助感至今歷歷在目。但現在,我可以在 90 秒內從零建立一個企業級的現代化開發環境,而且這個環境具備未來 3-5 年的技術前瞻性。
這不僅僅是工具的進步,更是整個前端工程思維的革命性升級。
<!-- 原始的開發方式 -->
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="jquery.min.js"></script>
</head>
<body>
<div id="app">
<h1>My Website</h1>
</div>
<script>
// 直接在 HTML 中寫 JavaScript
$(document).ready(function() {
$('#app').append('<p>Hello World!</p>');
});
</script>
</body>
</html>
特徵分析:
// webpack.config.js - 200+ 行的設定地獄
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
entry: {
main: './src/index.js',
vendor: ['react', 'react-dom', 'lodash']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: isProduction
? '[name].[contenthash:8].js'
: '[name].js',
chunkFilename: isProduction
? '[name].[contenthash:8].chunk.js'
: '[name].chunk.js',
publicPath: '/',
clean: true
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
browsers: ['> 1%', 'last 2 versions']
},
useBuiltIns: 'usage',
corejs: 3
}],
'@babel/preset-react'
],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-syntax-dynamic-import'
]
}
}
},
{
test: /\.css$/,
use: [
isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
type: 'asset/resource',
generator: {
filename: 'images/[name].[contenthash:8][ext]'
}
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html',
minify: isProduction ? {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true
} : false
}),
...(isProduction ? [
new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css',
chunkFilename: '[name].[contenthash:8].chunk.css'
})
] : [])
],
optimization: {
minimize: isProduction,
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
priority: 10
},
common: {
name: 'common',
minChunks: 2,
chunks: 'all',
priority: 5,
reuseExistingChunk: true
}
}
}
},
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 3000,
hot: true,
historyApiFallback: true,
overlay: {
warnings: false,
errors: true
}
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
}
}
};
};
痛點深度分析:
# 現代化開發體驗:一鍵啟動
$ npm create vite@latest my-modern-app -- --template react-ts
$ cd my-modern-app
$ npm install
$ npm run dev
VITE v4.5.0 ready in 347 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h to show help
// vite.config.ts - 簡潔而強大
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
server: {
port: 3000,
open: true,
},
build: {
target: 'esnext',
minify: 'esbuild',
},
})
革命性優勢:
基於我 5 年來在不同規模專案中的實戰經驗,我總結出這套技術選型決策框架:
專案規模 | 團隊規模 | 推薦工具 | 核心考量 | 實際案例 |
---|---|---|---|---|
🏠 小型專案 | 1-3 人 | Vite + SWC | 快速啟動,簡單維護 | 個人作品集、MVP 原型 |
🏢 中型專案 | 4-10 人 | Vite + TypeScript | 型別安全,團隊協作 | 企業官網、管理後台 |
🏭 大型專案 | 10+ 人 | Vite + Turborepo | Monorepo 管理,擴展性 | 電商平台、SaaS 產品 |
🔧 Legacy 遷移 | 任意 | Webpack 5 + Module Federation | 漸進式遷移,相容性 | 舊系統現代化改造 |
// Vite 的核心優勢:基於 ESM 的依賴預構建
// 傳統 Webpack 方式
const lodash = require('lodash'); // 執行時解析,每次都要重新打包
// Vite 方式
import { debounce } from 'lodash-es'; // 編譯時最佳化,只打包使用的函式
// 效能對比實測資料(基於真實專案)
const performanceComparison = {
coldStart: {
webpack: '45-60s',
vite: '0.3-0.8s',
improvement: '98%+'
},
hotReload: {
webpack: '2-5s',
vite: '50-200ms',
improvement: '95%+'
},
buildTime: {
webpack: '120-300s',
vite: '20-60s',
improvement: '80%+'
}
};
# Dockerfile.dev - 多階段構建策略
FROM node:18.17.0-alpine as base
# 安裝系統依賴
RUN apk add --no-cache \
git \
openssh-client \
python3 \
make \
g++
WORKDIR /app
# 依賴層(利用 Docker 層快取)
FROM base as deps
COPY package*.json ./
RUN npm ci --only=development && npm cache clean --force
# 開發環境層
FROM base as development
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 設置開發環境變數
ENV NODE_ENV=development
ENV CHOKIDAR_USEPOLLING=true
ENV HOST=0.0.0.0
ENV PORT=3000
# 暴露端口和除錯端口
EXPOSE 3000 9229
# 健康檢查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000 || exit 1
# 開發命令
CMD ["npm", "run", "dev"]
# docker-compose.dev.yml - 完整開發環境編排
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
target: development
ports:
- "3000:3000"
- "9229:9229" # Node.js 除錯端口
volumes:
- .:/app
- /app/node_modules # 防止覆蓋
- /app/dist # 防止覆蓋
environment:
- NODE_ENV=development
- VITE_API_URL=http://api:8000
depends_on:
- api
- db
networks:
- dev-network
restart: unless-stopped
api:
image: node:18.17.0-alpine
working_dir: /app
command: npm run dev
ports:
- "8000:8000"
volumes:
- ../api:/app
environment:
- NODE_ENV=development
- DB_URL=mongodb://db:27017/myapp
depends_on:
- db
networks:
- dev-network
db:
image: mongo:6.0-alpine
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=password
networks:
- dev-network
volumes:
mongodb_data:
networks:
dev-network:
driver: bridge
// vite.config.ts - 企業級設定範例
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react-swc'
import { resolve } from 'path'
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig(({ command, mode }) => {
// 載入環境變數
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [
react({
// 使用 SWC 獲得更快的編譯速度
jsxImportSource: '@emotion/react',
plugins: [['@swc/plugin-emotion', {}]]
}),
// 打包分析器(僅在分析模式下啟用)
...(mode === 'analyze' ? [
visualizer({
filename: 'dist/stats.html',
open: true,
gzipSize: true,
brotliSize: true,
})
] : [])
],
// 路徑別名設定
resolve: {
alias: {
'@': resolve(__dirname, './src'),
'@components': resolve(__dirname, './src/components'),
'@hooks': resolve(__dirname, './src/hooks'),
'@utils': resolve(__dirname, './src/utils'),
'@api': resolve(__dirname, './src/api'),
'@types': resolve(__dirname, './src/types'),
'@assets': resolve(__dirname, './src/assets'),
},
},
// 開發伺服器設定
server: {
port: parseInt(env.VITE_PORT) || 3000,
host: true, // 允許外部訪問
open: true, // 自動開啟瀏覽器
cors: true,
// API 代理設定
proxy: {
'/api': {
target: env.VITE_API_URL || 'http://localhost:8000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
configure: (proxy, options) => {
// 代理事件監聽
proxy.on('proxyReq', (proxyReq, req, res) => {
console.log('Proxying request:', req.method, req.url);
});
}
},
// WebSocket 代理(適用於即時功能)
'/ws': {
target: 'ws://localhost:8080',
ws: true,
}
},
// 熱更新設定
hmr: {
overlay: true, // 顯示錯誤覆蓋層
}
},
// 構建設定
build: {
target: 'esnext',
minify: 'esbuild', // 使用 esbuild 進行壓縮
sourcemap: mode === 'development',
// 輸出目錄
outDir: 'dist',
assetsDir: 'assets',
// Rollup 設定
rollupOptions: {
output: {
// 手動程式碼分割
manualChunks: {
// 第三方庫分離
vendor: ['react', 'react-dom', 'react-router-dom'],
ui: ['@headlessui/react', '@heroicons/react'],
utils: ['lodash-es', 'date-fns', 'uuid'],
// 根據功能模組分割
auth: ['./src/modules/auth'],
dashboard: ['./src/modules/dashboard'],
},
// 檔案命名策略
chunkFileNames: (chunkInfo) => {
const facadeModuleId = chunkInfo.facadeModuleId
if (facadeModuleId?.includes('node_modules')) {
return 'vendor/[name].[hash].js'
}
return 'chunks/[name].[hash].js'
},
assetFileNames: (assetInfo) => {
const info = assetInfo.name.split('.')
const ext = info[info.length - 1]
if (/\.(png|jpe?g|svg|gif|tiff|bmp|ico)$/i.test(assetInfo.name)) {
return `images/[name].[hash].${ext}`
}
if (/\.(css)$/i.test(assetInfo.name)) {
return `css/[name].[hash].${ext}`
}
return `assets/[name].[hash].${ext}`
}
}
},
// 效能最佳化
chunkSizeWarningLimit: 1000, // 提高 chunk 大小警告閾值
// 生產環境最佳化
...(mode === 'production' && {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // 移除 console
drop_debugger: true, // 移除 debugger
pure_funcs: ['console.log'], // 移除特定函式調用
},
mangle: {
safari10: true, // 解決 Safari 10 問題
},
},
}),
},
// CSS 設定
css: {
modules: {
// CSS Modules 設定
localsConvention: 'camelCase',
scopeBehaviour: 'local',
generateScopedName: mode === 'development'
? '[name]__[local]__[hash:base64:5]'
: '[hash:base64:8]'
},
preprocessorOptions: {
scss: {
additionalData: `
@import "@/styles/variables.scss";
@import "@/styles/mixins.scss";
`,
javascriptEnabled: true,
},
},
devSourcemap: mode === 'development', // 開發環境啟用 CSS sourcemap
},
// 環境變數設定
define: {
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
__BUILD_TIME__: JSON.stringify(new Date().toISOString()),
__COMMIT_HASH__: JSON.stringify(process.env.COMMIT_HASH || 'dev'),
},
// 依賴最佳化
optimizeDeps: {
include: [
'react',
'react-dom',
'react-router-dom',
'@headlessui/react',
'lodash-es',
],
exclude: [
// 排除某些依賴的預構建
'@vite/client',
'@vite/env',
],
},
// 測試設定(如果使用 Vitest)
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts'],
},
}
})
// scripts/setup-ai-tools.ts - AI 工具自動設定
import { execSync } from 'child_process'
import { writeFileSync, readFileSync } from 'fs'
import { join } from 'path'
interface AIToolConfig {
name: string
enabled: boolean
config: Record<string, any>
}
class AIDevEnvironmentSetup {
private aiTools: AIToolConfig[] = [
{
name: 'GitHub Copilot',
enabled: true,
config: {
suggestions: true,
autoComplete: true,
codeReview: true
}
},
{
name: 'CodeWhisperer',
enabled: false, // 與 Copilot 互斥
config: {
language: 'typescript',
framework: 'react'
}
},
{
name: 'Tabnine',
enabled: true,
config: {
teamLearning: false, // 保護程式碼隱私
localMode: true
}
}
]
async setupAITools(): Promise<void> {
console.log('🤖 設置 AI 輔助開發工具...')
// 1. 設定 VSCode AI 擴展
await this.configureVSCodeAI()
// 2. 設置 AI 程式碼品質檢查
await this.setupAICodeQuality()
// 3. 設定 AI 測試生成
await this.setupAITesting()
console.log('✅ AI 開發環境設定完成!')
}
private async configureVSCodeAI(): Promise<void> {
const vscodeSettings = {
"github.copilot.enable": {
"*": true,
"yaml": false,
"plaintext": false,
"markdown": true,
"typescript": true,
"javascript": true,
"typescriptreact": true,
"javascriptreact": true
},
"github.copilot.editor.enableAutoCompletions": true,
"tabnine.experimentalAutoImports": true,
"editor.inlineSuggest.enabled": true,
"editor.suggestOnTriggerCharacters": true,
}
const settingsPath = join(process.cwd(), '.vscode', 'settings.json')
writeFileSync(settingsPath, JSON.stringify(vscodeSettings, null, 2))
}
private async setupAICodeQuality(): Promise<void> {
// 設定 AI 程式碼審查工具
const aiLintConfig = {
extends: ['@ai-lint/recommended'],
rules: {
'ai-lint/code-smell-detection': 'warn',
'ai-lint/performance-optimization': 'error',
'ai-lint/security-vulnerability': 'error'
}
}
writeFileSync('.ai-lintrc.json', JSON.stringify(aiLintConfig, null, 2))
}
private async setupAITesting(): Promise<void> {
// 安裝 AI 測試生成工具
try {
execSync('npm install -D @ai-test/generator', { stdio: 'inherit' })
const testConfig = {
generator: 'ai-test',
framework: 'vitest',
coverage: 80,
smartGeneration: true
}
writeFileSync('ai-test.config.js', `module.exports = ${JSON.stringify(testConfig, null, 2)}`)
} catch (error) {
console.warn('⚠️ AI 測試工具安裝失敗,跳過此步驟')
}
}
}
// 執行 AI 環境設置
new AIDevEnvironmentSetup().setupAITools()
// src/utils/dev-performance-monitor.ts - 開發時效能監控
export class DevPerformanceMonitor {
private static instance: DevPerformanceMonitor
private metrics: Map<string, number[]> = new Map()
private observers: PerformanceObserver[] = []
static getInstance(): DevPerformanceMonitor {
if (!DevPerformanceMonitor.instance) {
DevPerformanceMonitor.instance = new DevPerformanceMonitor()
}
return DevPerformanceMonitor.instance
}
init(): void {
if (process.env.NODE_ENV !== 'development') return
this.setupPerformanceObservers()
this.setupHMRMonitoring()
this.setupMemoryMonitoring()
this.setupNetworkMonitoring()
}
private setupPerformanceObservers(): void {
// 監控 Largest Contentful Paint
const lcpObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`🚀 LCP: ${entry.startTime.toFixed(2)}ms`)
this.recordMetric('lcp', entry.startTime)
}
})
lcpObserver.observe({ entryTypes: ['largest-contentful-paint'] })
this.observers.push(lcpObserver)
// 監控 First Input Delay
const fidObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`⚡ FID: ${entry.processingStart - entry.startTime}ms`)
this.recordMetric('fid', entry.processingStart - entry.startTime)
}
})
fidObserver.observe({ entryTypes: ['first-input'] })
this.observers.push(fidObserver)
// 監控 Cumulative Layout Shift
const clsObserver = new PerformanceObserver((list) => {
let clsValue = 0
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value
}
}
if (clsValue > 0) {
console.log(`📐 CLS: ${clsValue.toFixed(4)}`)
this.recordMetric('cls', clsValue)
}
})
clsObserver.observe({ entryTypes: ['layout-shift'] })
this.observers.push(clsObserver)
}
private setupHMRMonitoring(): void {
// 監控 Hot Module Replacement 效能
if (import.meta.hot) {
const start = performance.now()
import.meta.hot.on('vite:beforeUpdate', () => {
this.recordMetric('hmr-start', performance.now())
})
import.meta.hot.on('vite:afterUpdate', () => {
const hmrTime = performance.now() - start
console.log(`🔄 HMR Update: ${hmrTime.toFixed(2)}ms`)
this.recordMetric('hmr-duration', hmrTime)
})
}
}
private setupMemoryMonitoring(): void {
// 監控記憶體使用
setInterval(() => {
if ('memory' in performance) {
const memory = (performance as any).memory
const memoryUsage = {
used: Math.round(memory.usedJSHeapSize / 1048576 * 100) / 100,
total: Math.round(memory.totalJSHeapSize / 1048576 * 100) / 100,
limit: Math.round(memory.jsHeapSizeLimit / 1048576 * 100) / 100
}
if (memoryUsage.used > 50) { // 超過 50MB 時警告
console.warn(`🧠 Memory Usage: ${memoryUsage.used}MB / ${memoryUsage.limit}MB`)
}
this.recordMetric('memory-used', memoryUsage.used)
}
}, 10000) // 每 10 秒檢查一次
}
private setupNetworkMonitoring(): void {
// 監控網路請求
const networkObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
const networkEntry = entry as PerformanceResourceTiming
if (networkEntry.transferSize > 100000) { // 超過 100KB 的資源
console.warn(`📡 Large Resource: ${networkEntry.name} (${(networkEntry.transferSize / 1024).toFixed(2)}KB)`)
}
if (networkEntry.duration > 1000) { // 超過 1 秒的請求
console.warn(`⏱️ Slow Request: ${networkEntry.name} (${networkEntry.duration.toFixed(2)}ms)`)
}
}
})
networkObserver.observe({ entryTypes: ['resource'] })
this.observers.push(networkObserver)
}
private recordMetric(name: string, value: number): void {
if (!this.metrics.has(name)) {
this.metrics.set(name, [])
}
this.metrics.get(name)!.push(value)
// 保持最近 100 筆記錄
const values = this.metrics.get(name)!
if (values.length > 100) {
values.shift()
}
}
getMetricsSummary(): Record<string, any> {
const summary: Record<string, any> = {}
for (const [name, values] of this.metrics.entries()) {
if (values.length === 0) continue
summary[name] = {
count: values.length,
avg: values.reduce((a, b) => a + b, 0) / values.length,
min: Math.min(...values),
max: Math.max(...values),
latest: values[values.length - 1]
}
}
return summary
}
exportMetrics(): void {
const summary = this.getMetricsSummary()
console.table(summary)
// 可以整合到 CI/CD 流程中
if (process.env.CI) {
console.log('📊 Performance Metrics:', JSON.stringify(summary, null, 2))
}
}
destroy(): void {
this.observers.forEach(observer => observer.disconnect())
this.metrics.clear()
}
}
// 自動初始化
if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {
const monitor = DevPerformanceMonitor.getInstance()
monitor.init()
// 在控制台中提供全域方法
;(window as any).devPerf = {
summary: () => monitor.getMetricsSummary(),
export: () => monitor.exportMetrics()
}
}
// .vscode/settings.json - 團隊統一設定
{
// 編輯器核心設定
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.detectIndentation": false,
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.organizeImports": true,
"source.removeUnusedImports": true
},
// TypeScript 智能提示
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.suggest.autoImports": true,
"typescript.updateImportsOnFileMove.enabled": "always",
"typescript.inlayHints.parameterNames.enabled": "all",
"typescript.inlayHints.functionLikeReturnTypes.enabled": true,
// React 開發增強
"emmet.includeLanguages": {
"javascript": "javascriptreact",
"typescript": "typescriptreact"
},
"emmet.triggerExpansionOnTab": true,
// 檔案關聯
"files.associations": {
"*.css": "tailwindcss",
".env*": "dotenv",
"*.mdx": "mdx"
},
// 搜尋設定
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/build": true,
"**/.git": true,
"**/.next": true,
"**/coverage": true
},
// 檔案監視設定
"files.watcherExclude": {
"**/node_modules/**": true,
"**/dist/**": true,
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true
},
// Git 設定
"git.autofetch": true,
"git.confirmSync": false,
"git.enableSmartCommit": true,
// 路徑智能提示
"path-intellisense.mappings": {
"@": "${workspaceRoot}/src",
"@components": "${workspaceRoot}/src/components",
"@hooks": "${workspaceRoot}/src/hooks",
"@utils": "${workspaceRoot}/src/utils",
"@api": "${workspaceRoot}/src/api",
"@types": "${workspaceRoot}/src/types"
},
// CSS Modules 支援
"cssModules.camelCase": true,
// 顏色主題(統一團隊視覺體驗)
"workbench.colorTheme": "One Dark Pro",
"workbench.iconTheme": "material-icon-theme",
// 除錯設定
"debug.console.fontSize": 14,
"debug.inlineValues": "auto",
// 終端設定
"terminal.integrated.fontSize": 14,
"terminal.integrated.fontFamily": "FiraCode Nerd Font, Monaco, Menlo",
// AI 助手設定
"github.copilot.enable": {
"*": true,
"yaml": false,
"plaintext": false
}
}
// .vscode/extensions.json - 推薦團隊擴展
{
"recommendations": [
// 核心開發工具
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"ms-vscode.vscode-typescript-next",
// React 開發
"dsznajder.es7-react-js-snippets",
"formulahendry.auto-rename-tag",
// CSS 和樣式
"bradlc.vscode-tailwindcss",
"styled-components.vscode-styled-components",
// Git 工具
"eamodio.gitlens",
"github.vscode-pull-request-github",
// 開發體驗增強
"christian-kohler.path-intellisense",
"christian-kohler.npm-intellisense",
"gruntfuggly.todo-tree",
"pkief.material-icon-theme",
// AI 助手
"github.copilot",
"github.copilot-chat",
// 測試工具
"vitest.explorer",
// 文件工具
"yzhang.markdown-all-in-one",
// 其他實用工具
"humao.rest-client",
"ms-vscode.live-server",
"ritwickdey.liveserver"
],
"unwantedRecommendations": [
// 避免衝突的擴展
"hookyqr.beautify",
"ms-vscode.vscode-json"
]
}
// package.json - 完整的 npm scripts
{
"scripts": {
// 開發相關
"dev": "vite --host",
"dev:debug": "vite --host --mode debug",
"dev:https": "vite --host --https",
// 建構相關
"build": "tsc && vite build",
"build:analyze": "npm run build && npm run analyze",
"build:profile": "tsc && vite build --mode profile",
"preview": "vite preview",
// 程式碼品質
"lint": "eslint src --ext .ts,.tsx,.js,.jsx --max-warnings 0",
"lint:fix": "eslint src --ext .ts,.tsx,.js,.jsx --fix",
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,css,scss,md}\"",
"format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,css,scss,md}\"",
"type-check": "tsc --noEmit",
// 測試相關
"test": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest --coverage",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
// 分析工具
"analyze": "rollup-plugin-visualizer dist/stats.html",
"bundle-size": "npm run build && bundlesize",
// Git hooks
"prepare": "husky install",
"pre-commit": "lint-staged",
"pre-push": "npm run type-check && npm run test:coverage",
// 環境健康檢查
"health-check": "node scripts/health-check.js",
"doctor": "npm run health-check && npm audit && npm outdated",
// 清理操作
"clean": "rimraf dist node_modules/.vite",
"clean:all": "rimraf dist node_modules package-lock.json && npm install",
// 部署相關
"deploy:staging": "npm run build && aws s3 sync dist/ s3://my-app-staging",
"deploy:production": "npm run build && aws s3 sync dist/ s3://my-app-production"
},
"lint-staged": {
"src/**/*.{ts,tsx,js,jsx}": [
"eslint --fix",
"prettier --write"
],
"src/**/*.{css,scss,less}": [
"prettier --write"
],
"*.{md,json}": [
"prettier --write"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"pre-push": "npm run type-check && npm run test --run",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
}
讓我們實際演練如何在 5 分鐘內建立一個具備前瞻性的企業級開發環境:
# 使用最新的 Vite 模板
npm create vite@latest my-enterprise-app -- --template react-ts
cd my-enterprise-app
# 快速安裝核心依賴
npm install
# 安裝開發工具鏈
npm install -D \
@types/node \
@vitejs/plugin-react-swc \
eslint \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser \
prettier \
eslint-config-prettier \
husky \
lint-staged \
vitest \
@testing-library/react \
@testing-library/jest-dom
# 安裝生產依賴
npm install \
react-router-dom \
@tanstack/react-query \
axios \
zustand \
@headlessui/react \
@heroicons/react \
tailwindcss
// scripts/quick-setup.ts - 一鍵設定腳本
import { writeFileSync, mkdirSync } from 'fs'
import { execSync } from 'child_process'
const configs = {
// ESLint 設定
'.eslintrc.json': {
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
rules: {
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'off'
}
},
// Prettier 設定
'.prettierrc': {
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'es5'
},
// Tailwind 設定
'tailwind.config.js': `
module.exports = {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: { extend: {} },
plugins: []
}
`,
// Vitest 設定
'vitest.config.ts': `
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react-swc'
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts']
}
})
`
}
// 批量創建設定檔案
for (const [filename, content] of Object.entries(configs)) {
writeFileSync(filename, typeof content === 'string' ? content : JSON.stringify(content, null, 2))
}
// 初始化 Git hooks
execSync('npx husky install')
execSync('npx husky add .husky/pre-commit "npx lint-staged"')
console.log('✅ 企業級開發環境設定完成!')
# 執行設定腳本
npx tsx scripts/quick-setup.ts
# 啟動開發環境
npm run dev
# 🎉 完成!開發環境準備就緒
⚡ 驗證清單:
基於我對技術演進的深度觀察,未來 5 年開發環境將朝這些方向發展:
// 未來的開發環境可能是這樣的
$ ai-create-app my-project --description="電商平台,需要使用者認證、商品管理、支付整合"
// AI 自動分析需求並生成:
// ✅ 最適合的技術棧
// ✅ 完整的專案結構
// ✅ 基礎功能模組
// ✅ 最佳化的設定
// ✅ 測試用例範本
Creating optimized e-commerce platform...
├── Tech Stack: Next.js 15 + TypeScript + Tailwind
├── Database: Supabase (PostgreSQL)
├── Authentication: NextAuth.js
├── Payments: Stripe
├── State Management: Zustand
└── Testing: Vitest + Playwright
🚀 Project ready in 30 seconds!
# .devcontainer/devcontainer.json - 雲端開發環境標準化
{
"name": "Modern Web Development",
"image": "mcr.microsoft.com/devcontainers/typescript-node:18",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker": {},
"ghcr.io/microsoft/ai-copilot-devcontainer": {
"version": "latest"
}
},
"customizations": {
"vscode": {
"extensions": [
"github.copilot",
"ms-vscode.vscode-typescript-next"
]
}
},
"forwardPorts": [3000, 8000],
"postCreateCommand": "npm install && npm run setup:ai",
"remoteUser": "node"
}
// 未來的實時協作開發可能是這樣
interface CollaborativeSession {
participants: Developer[]
sharedState: {
codebase: RealtimeCodebase
terminal: SharedTerminal
debugger: CollaborativeDebugger
}
aiAssistant: {
codeReview: boolean
suggestionSharing: boolean
conflictResolution: boolean
}
}
// 多人即時編輯同一個檔案,類似 Google Docs
// AI 即時分析程式碼衝突並提供合併建議
// 共享開發環境,包含終端、除錯器、測試結果