完整的 Express + Vue3 日志齐全一体化项目模板

93 阅读4分钟

下面我将为你生成一个 完整的 Express + Vue3 一体化项目模板,采用 pnpm 作为包管理器,支持:

✅ 开发模式:Vite 热更新 + Express API + 请求日志
✅ 代理功能:Vite 代理 API 到 Express
✅ 构建模式:打包 Vue3,由 Express 托管静态文件
✅ 请求日志:Express 记录所有 API 和页面访问
✅ 使用 pnpm 管理依赖,高效省空间


📁 项目结构

fullstack-vue-express/
├── backend/
│   ├── server.mjs          # Express 服务器(ESM)
│   ├── routes/             # API 路由
│   │   └── api.js
│   └── package.json
├── frontend/
│   ├── src/
│   │   ├── App.vue
│   │   └── main.js
│   ├── index.html
│   ├── vite.config.js      # Vite 配置(含代理)
│   └── package.json
├── dist/                   # 构建后前端文件(git 忽略)
├── pnpm-workspace.yaml     # 启用 pnpm workspace
├── .npmrc                  # 指定包管理器
└── package.json            # 根目录脚本

🛠️ 第一步:初始化项目

# 创建项目根目录
mkdir fullstack-vue-express
cd fullstack-vue-express

# 初始化 pnpm workspace
echo "packages:
  - 'backend'
  - 'frontend'" > pnpm-workspace.yaml

# 设置包管理器
echo "package-manager=pnpm@9.0.0" > .npmrc

# 根目录 package.json(统一脚本)
cat > package.json <<EOF
{
  "name": "fullstack-vue-express",
  "private": true,
  "scripts": {
    "dev": "pnpm --filter backend start & pnpm --filter frontend dev",
    "build": "pnpm --filter frontend build && pnpm --filter backend build",
    "preview": "node backend/server.mjs"
  }
}
EOF

🎯 第二步:创建前端(Vue3 + Vite)

mkdir frontend
cd frontend

# 初始化 Vue3 项目(Vite + Vue)
pnpm create vite@latest . -- --template vue

# 安装依赖
pnpm install

# 修改 vite.config.js 支持代理
cat > vite.config.js <<EOF
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  server: {
    port: 5173,
    host: 'localhost',
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        configure: (proxy, options) => {
          proxy.on('proxyReq', (proxyReq, req, res) => {
            console.log('[Vite Proxy] → API:', req.method, req.url)
          })
        }
      }
    }
  }
})
EOF

# 修改 App.vue 简化示例
cat > src/App.vue <<'EOF'
<script setup>
import { ref, onMounted } from 'vue'

const message = ref('')

onMounted(async () => {
  const res = await fetch('/api/hello')
  const data = await res.json()
  message.value = data.message
})
</script>

<template>
  <div class="container">
    <h1>🚀 Express + Vue3 一体化项目</h1>
    <p>API 返回: <strong>{{ message }}</strong></p>
  </div>
</template>

<style>
.container {
  text-align: center;
  margin-top: 100px;
  font-size: 1.5em;
  color: #2c3e50;
}
</style>
EOF

🖥️ 第三步:创建后端(Express + ESM)

cd ..
mkdir backend
cd backend

# 初始化
pnpm init -y

# 安装依赖
pnpm add express cors
pnpm add -D http-proxy-middleware

# 创建 server.mjs
cat > server.mjs <<'EOF'
import express from 'express'
import cors from 'cors'
import { createProxyMiddleware } from 'http-proxy-middleware'
import { fileURLToPath } from 'url'
import { dirname, join } from 'path'

const app = express()
const PORT = 3000

// __dirname 兼容 ESM
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

// 日志中间件
app.use((req, res, next) => {
  console.log(
    '[Request]', 
    new Date().toISOString().split('T')[1].split('.')[0],
    req.method.padEnd(4),
    req.path,
    '←',
    req.ip.replace('::1', 'localhost')
  )
  next()
})

// API 路由
app.use('/api', (req, res, next) => {
  console.log(`[API] ${req.method} ${req.path} 来自 ${req.ip}`)
  next()
}, cors())

app.get('/api/hello', (req, res) => {
  res.json({ message: 'Hello from Express! 🎉' })
})

// 开发模式:代理静态资源到 Vite(用于 dev)
if (process.env.NODE_ENV !== 'production') {
  app.use(
    createProxyMiddleware({
      target: 'http://localhost:5173',
      changeOrigin: true,
      bypass: (req) => {
        // API 请求不代理
        if (req.path.startsWith('/api')) return req
      },
      onProxyReq: (proxyReq, req, res) => {
        console.log('[Proxy] → Frontend:', req.method, req.path)
      }
    })
  )
} else {
  // 生产模式:托管构建后的静态文件
  app.use(express.static(join(__dirname, '../dist')))
  app.get('*', (req, res) => {
    res.sendFile(join(__dirname, '../dist', 'index.html'))
  })
}

app.listen(PORT, () => {
  console.log(`\n🚀 Express 服务器运行在 http://localhost:${PORT}`)
  console.log(`   开发模式: 代理请求到 Vite`)
  console.log(`   生产模式: 托管 dist/ 静态文件\n`)
})
EOF

# 创建 package.json 脚本
cat > package.json <<'EOF'
{
  "name": "backend",
  "type": "module",
  "scripts": {
    "start": "node server.mjs",
    "build": "echo 'Backend build placeholder'"
  }
}
EOF

🚀 第四步:启动项目

1. 启动开发模式(热更新)

# 在项目根目录运行
pnpm dev

会同时启动:

  • Vite 前端:http://localhost:5173
  • Express 后端:http://localhost:3000

🔍 访问 http://localhost:3000,所有请求都会经过 Express,你会看到完整日志!

2. 构建生产版本

pnpm build

会:

  • 构建 Vue3 到 dist/
  • 准备 Express 托管

3. 预览生产版本

pnpm preview

访问 http://localhost:3000,Express 直接 serve 静态文件。


📊 日志示例(开发模式)

[Request] 14:30:21 GET  /api/hello ← ::1
[API] GET /api/hello 来自 ::1
[Request] 14:30:22 GET  / ← ::1
[Proxy] → Frontend: GET /
[Vite Proxy] → API: GET /api/hello

✅ 功能总结

功能是否支持
使用 pnpm
Vue3 热更新
Express API
请求日志
Vite 代理 API
生产构建 + 托管
一体化启动脚本pnpm dev

📦 下一步建议

  1. ✅ 将项目推送到 GitHub
  2. ✅ 添加 .gitignore
node_modules/
dist/
.env
  1. ✅ 添加 README.md 说明

🎁 附加:一键复制完整命令(Linux/Mac)

# 全自动创建项目(复制粘贴即可)
mkdir fullstack-vue-express && cd fullstack-vue-express
echo "packages:
  - 'backend'
  - 'frontend'" > pnpm-workspace.yaml
echo "package-manager=pnpm@9.0.0" > .npmrc
cat > package.json <<EOF
{
  "name": "fullstack-vue-express",
  "private": true,
  "scripts": {
    "dev": "pnpm --filter backend start & pnpm --filter frontend dev",
    "build": "pnpm --filter frontend build && pnpm --filter backend build",
    "preview": "node backend/server.mjs"
  }
}
EOF

mkdir frontend && cd frontend
pnpm create vite@latest . -- --template vue
pnpm install

cat > vite.config.js <<'EOF'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
  plugins: [vue()],
  server: {
    port: 5173,
    host: 'localhost',
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        configure: (proxy, options) => {
          proxy.on('proxyReq', (proxyReq, req, res) => {
            console.log('[Vite Proxy] → API:', req.method, req.url)
          })
        }
      }
    }
  }
})
EOF

cat > src/App.vue <<'EOF'
<script setup>
import { ref, onMounted } from 'vue'
const message = ref('')
onMounted(async () => {
  const res = await fetch('/api/hello')
  const data = await res.json()
  message.value = data.message
})
</script>
<template>
  <div class="container">
    <h1>🚀 Express + Vue3 一体化项目</h1>
    <p>API 返回: <strong>{{ message }}</strong></p>
  </div>
</template>
<style>
.container {
  text-align: center;
  margin-top: 100px;
  font-size: 1.5em;
  color: #2c3e50;
}
</style>
EOF

cd ..
mkdir backend && cd backend
pnpm init -y
pnpm add express cors
pnpm add -D http-proxy-middleware

cat > server.mjs <<'EOF'
import express from 'express'
import cors from 'cors'
import { createProxyMiddleware } from 'http-proxy-middleware'
import { fileURLToPath } from 'url'
import { dirname, join } from 'path'
const app = express()
const PORT = 3000
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
app.use((req, res, next) => {
  console.log('[Request]', new Date().toISOString().split('T')[1].split('.')[0], req.method.padEnd(4), req.path, '←', req.ip.replace('::1', 'localhost'))
  next()
})
app.use('/api', (req, res, next) => {
  console.log(\`[API] \${req.method} \${req.path} 来自 \${req.ip}\`)
  next()
}, cors())
app.get('/api/hello', (req, res) => {
  res.json({ message: 'Hello from Express! 🎉' })
})
if (process.env.NODE_ENV !== 'production') {
  app.use(createProxyMiddleware({
    target: 'http://localhost:5173',
    changeOrigin: true,
    bypass: (req) => req.path.startsWith('/api') ? req : null,
    onProxyReq: (proxyReq, req, res) => {
      console.log('[Proxy] → Frontend:', req.method, req.path)
    }
  }))
} else {
  app.use(express.static(join(__dirname, '../dist')))
  app.get('*', (req, res) => {
    res.sendFile(join(__dirname, '../dist', 'index.html'))
  })
}
app.listen(PORT, () => {
  console.log(`\\n🚀 Express 服务器运行在 http://localhost:\${PORT}`)
  console.log('   开发模式: 代理请求到 Vite')
  console.log('   生产模式: 托管 dist/ 静态文件\\n')
})
EOF

cat > package.json <<'EOF'
{
  "name": "backend",
  "type": "module",
  "scripts": {
    "start": "node server.mjs",
    "build": "echo 'Backend build placeholder'"
  }
}
EOF

echo "✅ 项目创建完成!运行 pnpm dev 启动开发服务器"

🎉 恭喜!你现在拥有了一个 现代化、一体化、日志齐全、生产可用的 Express + Vue3 项目模板,可以直接用于学习、开发或部署!