Cada aplicación necesita ajustes de configuración y la mayoría de los lenguajes de programación / ecosistemas tiene algún tipo de soporte y convención por defecto para él.
- La mayoría de las aplicaciones Java se basan en archivos .properties;
- .Net tiene sus archivos estándar app.config y web.config;
- Ruby on Rails carga la configuración desde config/application.rb, Initializers and After-initializers;
- Node.js no tiene una forma estándar de administrar estos ajustes, pero hay muchas opciones disponibles.
- Overview
- Init
- ExpressJS
- Config Express JS
- Api Folder
- Routing
- Config Environment
- Hot Reloading
- NPM Scripts
- Thank You
- Folder-by-type or Folder-by-feature
Folder-by-type
com.example
├── domain
│ ├── User.js
│ └── Pet.js
├── controllers
│ ├── UserController.js
│ └── PetController.js
├── repositories
│ ├── UserRepository.js
│ └── PetRepository.js
├── services
│ ├── UserService.js
│ └── PetService.js
│ // and everything else in the project
└── index.js
Folder-by-feature
com.example
├── pet
│ ├── Pet.js
│ ├── pet.controller.js
│ ├── pet.model.js
│ └── pet.service.js
├── user
│ ├── user.js
│ ├── userController.java
│ ├── user.model.js
│ └── user.service.js
│ // and everything else in the project
└── index.js
- Create the basis of our project package.json run
npm init
- Settings for editors .editorconfig
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
- Linter .eslintrc
{
"env": {
"node": true,
"es6": true
},
"extends": "airbnb-base",
"parser": "babel-eslint"
}
- Modules required for the linter
npm i -D eslint eslint-config-airbnb-base babel-eslint eslint-plugin-import
npm i -S express
- app.js
/**
* Main application file
*/
const express = require('express');
const http = require('http');
// Setup server
const app = express();
const server = http.createServer(app);
const config = {
port: 8080,
ip: '127.0.0.1',
};
// Start server
function startServer() {
app.nodeMDE = server.listen(config.port, config.ip, () => {
console.log(`Express server listening on ${config.port}, in ${app.get('env')} mode`);
});
}
setImmediate(startServer);
// Expose app
module.exports = app;
- index.js
// Export the application
module.exports = require('./app');
- Install
npm i -S compression body-parser method-override errorhandler
- config/express.js
/**
* Express configuration
* @author: Cristian Moreno Zulauaga <[email protected]>
*/
const compression = require('compression');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const errorHandler = require('errorhandler');
module.exports = (app) => {
const env = app.get('env');
app.use(compression());
app.use(bodyParser.urlencoded({ extended: false, limit: '50mb' }));
app.use(bodyParser.json({ limit: '50mb' }));
app.use(methodOverride());
if (env === 'development' || env === 'test') {
app.use(errorHandler()); // Error handler - has to be last
}
};
- Update app.js
const express = require('express');
const http = require('http');
// Add this line
const expressConfig = require('./config/express');
const app = express();
const server = http.createServer(app);
// Add this line
expressConfig(app);
- Create
api/<your_api_endpoint>
exampleapi/user api/car
- In this folder it is common to have the files for models, services, events, controllers etc
- index.js
/**
* User
* @author: Cristian Moreno Zuluaga <[email protected]>
*/
const { Router } = require('express');
const controller = require('./helloWorld.controller');
const router = new Router();
// All Verbs
router.get('/', controller.index);
/*
router.delete('/:id', auth.hasRole('admin'), controller.destroy);
router.put('/:id/', auth.isAuthenticated(), controller.update);
router.get('/:id', auth.isAuthenticated(), controller.show);
router.post('/', controller.create);
*/
module.exports = router;
- helloWorld.controller.js
/**
* @author: Cristian Moreno Zuluaga <[email protected]>
*/
/**
* Show hello world
*/
function index(req, res) {
return res.status(200).json({ message: 'hello wolrd!!' });
}
module.exports = { index };
- routes.js
/**
* Main application routes
* @author: Cristian Moreno Zuluaga <[email protected]>
*/
// Import Endpoints
const helloWorld = require('./api/helloWorld');
module.exports = (app) => {
/* Others conf like CORS */
// Insert routes below
app.use('/api/helloworld', helloWorld);
// app.use('/api/users', user);
// app.use('/api/cars', car);
};
- Update app.js
...
const expressConfig = require('./config/express');
// Add this line
const routeConfig = require('./routes');
...
expressConfig(app);
// Add this line
routeConfig(app);
- Test browser
http://localhost:8080/api/helloworld
- config/environment/development.js
/**
* Development specific configuration
* @author: Cristian Moreno Zulauaga <[email protected]>
*/
module.exports = {
// MongoDB connection options
mongo: {
uri: 'mongodb://localhost/nodejs-scaffolding-dev',
},
// Seed database on startup
seedDB: false,
};
- config/environment/production.js
/**
* Production specific configuration
* @author: Cristian Moreno Zulauaga <[email protected]>
*/
module.exports = {
// Server IP
ip: process.env.OPENSHIFT_NODEJS_IP || process.env.IP || undefined,
// Server port
port: process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || 3030,
// MongoDB connection options
mongo: {
uri: process.env.MONGODB_URI ||
process.env.MONGOHQ_URL ||
process.env.OPENSHIFT_MONGODB_DB_URL +
process.env.OPENSHIFT_APP_NAME ||
'mongodb://localhost/nodejs-scaffolding',
},
};
- Shared specific configuration
config/environment/shared.js
Optional - Run
npm i -S lodash
config/environment/index.js
/**
* Default specific configuration
* @author: Cristian Moreno Zulauaga <[email protected]>
*/
const path = require('path');
const _ = require('lodash');
const shared = require('./shared');
const env = process.env.NODE_ENV || 'development';
let envFile = require('./development.js');
if (env === 'production') {
// Register the Babel require hook
envFile = require('./production.js');
}
// All configurations will extend these options
// ============================================
const all = {
env: process.env.NODE_ENV,
// Root path of server
root: path.normalize(__dirname + '/../../..'),
// Server port
port: process.env.PORT || 3030,
// Server IP
ip: process.env.IP || '0.0.0.0',
// Should we populate the DB with sample data?
seedDB: false,
// Secret for session, you will want to change this and make it an environment variable
secrets: {
session: 'nodejs-scaffolding-secret',
},
// MongoDB connection options
mongo: {
options: {
db: {
safe: true,
},
useMongoClient: true,
poolSize: 2,
},
},
facebook: {
clientID: process.env.FACEBOOK_ID || 'id',
clientSecret: process.env.FACEBOOK_SECRET || 'secret',
callbackURL: `${process.env.DOMAIN || ''}/auth/facebook/callback`,
},
twitter: {
clientID: process.env.TWITTER_ID || 'id',
clientSecret: process.env.TWITTER_SECRET || 'secret',
callbackURL: `${process.env.DOMAIN || ''}/auth/twitter/callback`,
},
google: {
clientID: process.env.GOOGLE_ID || 'id',
clientSecret: process.env.GOOGLE_SECRET || 'secret',
callbackURL: `${process.env.DOMAIN || ''}/auth/google/callback`,
},
};
// Export the config object based on the NODE_ENV
// ==============================================
module.exports = _.merge(all, shared, envFile || {});
- Update
app.js
// Add this import
const config = require('./config/environment');
// remove this lines
const config = {
port: 8080,
ip: '127.0.0.1',
};
...
- Run
npm i -D nodemon
- Verify
nodemon index.js
- Add to
package.json
...
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
},
...
❓❓❓❓❓❓
👏👏👏👏👏👏👏
Amazing ...