如何将Express.js项目与Azure Functions整合至单一代码库?
Express.js + Azure Functions 单代码库整合方案
一、项目结构设计
推荐采用模块化目录结构,将Express应用、Azure Functions和共享代码分离,同时保持在同一仓库内:
your-project/ ├── src/ │ ├── api/ # Express.js 应用代码 │ │ ├── routes/ │ │ ├── middleware/ │ │ ├── app.js │ │ └── package.json │ ├── functions/ # Azure Functions 代码 │ │ ├── sendReminder/ # 单个函数(发送提醒) │ │ │ ├── index.js │ │ │ └── function.json │ │ ├── anotherFunction/ │ │ └── package.json │ └── shared/ # 共享代码 │ ├── models/ # 数据模型(如用户、提醒) │ ├── db/ # 数据库连接逻辑 │ ├── utils/ # 通用工具函数(如邮件发送、日期处理) │ └── config.js # 共享配置(如环境变量读取) ├── .github/ │ └── workflows/ # CI/CD 工作流 │ └── deploy.yml ├── .gitignore └── README.md
- api/:保留原有Express应用的完整结构,不改变Web App部署逻辑
- functions/:每个子文件夹对应一个Azure Function,包含函数代码和
function.json配置文件 - shared/:存放所有通用逻辑,两边通过相对路径引用,彻底避免代码重复
二、共享代码的复用与隔离
1. 共享核心逻辑
将数据库连接、数据模型、通用工具等无环境依赖的代码放在shared/目录下,供两边共同调用:
// src/shared/db/connection.js const mongoose = require('mongoose'); const connectDB = async () => { try { await mongoose.connect(process.env.MONGODB_URI); console.log('数据库连接成功'); } catch (err) { console.error('数据库连接失败:', err); process.exit(1); } }; module.exports = connectDB;
Express应用和Functions的引用方式:
// src/api/app.js const connectDB = require('../shared/db/connection'); connectDB(); // src/functions/sendReminder/index.js const connectDB = require('../../shared/db/connection'); module.exports = async function (context, timer) { await connectDB(); // 执行提醒发送逻辑 };
2. 隔离特定逻辑
- Express特有的中间件、路由处理逻辑不要放入共享代码
- Functions特有的
context对象相关逻辑也不要写入共享代码,确保共享代码的环境中立性
三、部署配置与自动化
1. 依赖管理
推荐为Express和Functions分别维护package.json,避免版本冲突:
src/api/package.json:管理Express及相关依赖src/functions/package.json:管理Azure Functions SDK及相关依赖
2. CI/CD 工作流(GitHub Actions示例)
创建.github/workflows/deploy.yml,实现一次提交同时部署Web App和Functions:
name: 部署到Azure on: push: branches: [ main ] jobs: 部署WebApp: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 配置Node.js环境 uses: actions/setup-node@v4 with: node-version: '20' - name: 安装依赖 run: cd src/api && npm install - name: 部署到Azure Web App uses: azure/webapps-deploy@v3 with: app-name: ${{ secrets.AZURE_WEBAPP_NAME }} publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }} package: src/api 部署Functions: runs-on: ubuntu-latest needs: 部署WebApp steps: - uses: actions/checkout@v4 - name: 配置Node.js环境 uses: actions/setup-node@v4 with: node-version: '20' - name: 安装依赖 run: cd src/functions && npm install - name: 部署到Azure Functions uses: Azure/functions-action@v1 with: app-name: ${{ secrets.AZURE_FUNCTIONS_APP_NAME }} publish-profile: ${{ secrets.AZURE_FUNCTIONS_PUBLISH_PROFILE }} package: src/functions
需在GitHub仓库的Secrets中配置AZURE_WEBAPP_NAME、AZURE_WEBAPP_PUBLISH_PROFILE、AZURE_FUNCTIONS_APP_NAME、AZURE_FUNCTIONS_PUBLISH_PROFILE四个变量。
3. 环境变量统一管理
使用Azure App Configuration或Azure Key Vault存储敏感配置(如数据库连接字符串、API密钥),Express Web App和Azure Functions均通过应用设置读取这些变量,避免硬编码。
四、本地开发与调试
- Express本地运行:进入
src/api目录,执行npm start启动本地服务器 - Functions本地调试:使用Azure Functions Core Tools,进入
src/functions目录,执行func start启动本地函数运行时 - 共享代码热更新:用
nodemon监听shared/目录变化,修改共享代码后自动刷新两边服务
五、最佳实践
- 分支策略:采用主干开发或Git Flow模式,主分支部署生产环境,开发分支部署测试环境,确保两边版本同步
- 日志与监控:统一使用Azure Monitor收集两边日志,设置告警规则,及时排查问题
- 版本控制:所有代码(包括Functions的
function.json配置)均纳入版本控制,避免配置漂移 - 测试隔离:为Express和Functions分别编写单元测试、集成测试,共享代码的测试单独存放,确保逻辑正确性
内容的提问来源于stack exchange,提问作者user15303385
相关产品推荐
相关产品推荐

