多环境Express Api
我正在开发基于Express框架的多环境API。 我想要的是保持我的configurationdynamic,例如这个Api将能够同时提供移动应用程序和Web应用程序。 如果请求来自移动源,则应该包含config-app-2.json
,否则config-app-2.json
。
目前我有config-app-1.json
, config-app-2.json
, config-db-1.json
, config-db-2.json
和一个在app.listen()
设置所需configuration的configManager.js
类。 。 在其他应用程序模块中,我需要configManager
并使用必要的configuration。 然而,这会导致单个函数中的代码重复问题。 每个函数都必须在本地范围内获取数据库和应用程序设置的引用。
我想知道什么是使用Express框架的多环境API构build的最佳实践。
这些是configuration文件,这是我的方法。
文件结构
. ├── app.js ├── _configs | ├── configManager.js | ├── database.js | └── platform | ├── mobile.js | └── desktop.js
环境configuration
Configration文件是每个设备的js模块,然后configManager根据设备处理哪一个是活动的。
//mobile.js example module.exports = { device: 'mobile', configVar: 3000, urls: { base: 'DEVICE_SPECIFIC_BASE_URL', api: 'DEVICE_SPECIFIC_BASE_URL' }, mixpanelKey: 'DEVICE_SPECIFIC_BASE_URL', apiKey: "DEVICE_SPECIFIC_BASE_URL", }
数据库configuration
数据库configuration应该集中。
通常您可以连接到同一节点实例中的多个数据库,但不推荐使用。 如果你绝对必须使用两个对象(而不是“mongodb”replace为“mobileMongoDb”和“desktopMongoDb”),但我build议您使用一个数据库并将其分成两个主要文档,或者使用在您的平台中设置的某些前缀特定的configuration。
// databse.js example module.exports= { mongodb: { host : 'localhost', port : 27017, user : '', password : '', database : 'DB_NAME' }, }
configManager.js(把东西放在一起)
这是一个简单的文件仅供演示
var userAgent = req.headers['User-Agent']; var isMobile = /Mobile|Android|/i.test(userAgent); // require them all to be cached when you run node. var configs = { mobile: require('./platform/mobile' ), desktop: require('./platform/desktop' ) } var activeConfig = isMobile? configs.mobile : configs.desktop; var dbConfigs = require('./databse'); var mongoose = require('mongoose'); var express = require('express'); var app = express(); app.get('/', function (req, res) { var finalresp = 'Hello from '; finalresp += isMobile? 'mobile' : 'desktop; finalresp += activeConfig.configVar; res.send(finalresp); }); mongoose.connect(dbConfigs.mongodb.host, function(err) { if(isMobile) { /* ... */ } });
从头部检测移动
您可以设置环境variables。 我通常做的是有多个configuration文件,如你所说的。
然后在本地,开发和生产环境variablesNODE_ENV分别设置为“LOCAL”,“DEVELOPMENT”和“PRODUCTION”。
然后你可以通过下面的代码来引用环境
ENV = process.env.NODE_ENV if(ENV === 'PRODUCTION') { mainConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/main-production.json'))) dbConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/db-production.json'))) } else if(ENV === 'DEVELOPMENT') { mainConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/main-development.json'))) dbConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/db-development.json'))) } else if(ENV === 'LOCAL') { mainConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/main-local.json'))) dbConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/db-local.json'))) }
确保在每台服务器的环境中正确设置环境variables。 按照你想要的方式使用从上面的代码中检索的configurationjson。
请求的来源(例如Mobile – Web)可以在运行时更改吗? 换句话说,可以请求1来自移动设备并从networking请求2?
如果是这样,您可以查看标题中的用户代理来确定您正在处理的设备types。 这确实使你依赖于用户代理,如果没有发送,你将无法识别你的客户端。
req.headers['User-Agent'];
如果您自己拥有客户,则可以为每个请求添加一个属性,如额外的标题。 req.headers['X-Client-Type'] = 'Mobile'; //Web
req.headers['X-Client-Type'] = 'Mobile'; //Web
。
这样你就不依赖于用户代理,并且仍然能够识别每个客户的types。
最后,如果你正在和第三方客户打交道,那么其他人可能会打你的API来让你的应用程序注册。 (名称,开发人员姓名,联系信息,可能同意某种types的服务协议,并说明客户端types,Web vs Mobile)。
然后,您可以在每个新请求中获取每个客户端的types。
- Express + socket.io:socket.io客户端脚本是404
- 在node.jsexpression式中放置请求
- node.js + express 3 + socket.io =发送后无法设置标题
- 我如何从NodeJS / Expressnetworking应用程序运行CasperJS / PhantomJStesting?
- Async / Await – Typescript和ExpressJs
- expression4路线问题
- 如何在nodejs中模拟请求和响应来testing中间件/控制器?
- MongoDB与未知的findOne方法造成大的延迟 – New Relic
- express.js app.use(function理解问题