Contenido


Construya una aplicación de encuestas en tiempo real con Node.js, Express, AngularJS y MongoDB

Comments

Recientemente, mientras dábamos una cátedra sobre HTML5 a un grupo grande de estudiantes, yo quería encuestarlos y desplegar los resultados de su votación, actualizando en tiempo real. Decidí construir rápidamente una aplicación de encuestas para este propósito. Yo quería una arquitectura simple y no muchos idiomas y frameworks diferentes. Así que decidí usar JavaScript para todo — Node.js y Express para el lado del servidor, MongoDB para la base de datos y AngularJS para la interfaz del usuario de extremo delantero .

Este apilamiento MEAN (Mongo, Express, Angular, Node) podrá algún día sobrepasar la simplicidad del apilamiento LAMP (Linux, Apache, MySQL, PHP) para el desarrollo y el despliegue de la aplicación web.

Corra la aplicaciónObtenga el código

Yo elegí usar DevOps Services (anteriormente JazzHub)para administrar el código fuente para mi proyecto. No sólo me da un sistema de control de versión completa para mi código, sino que también tiene un IDE en línea para editar mi código en la nube y una función ágil abundante para la administración del proyecto. DevOps Services también se integra fácilmente con Eclipse, que tiene plug-ins para permitir el despliegue con un clic a plataformas tales como IBM Cloud o Cloud Foundry.

Lo que necesitará para construir su aplicación

Paso 1. Construir un back-end Express básico

En Eclipse, cambie a la perspectiva Node y cree un nuevo proyecto Node Express. Si crea un proyecto DevOps Services, como yo lo hice, designe su proyecto Node Express con el mismo nombre. Deje seleccionado a Jade como el motor de la plantilla. Eclipse descargará automáticamente los módulos npm requeridos para crear una simple aplicación Express.

Corra la aplicación Express

En Project Explorer, encuentre app.js en la raíz de su proyecto, dé un clic derecho y elija Run As > Node Application. Esto iniciará un servidor de Web y le desplegará la aplicación. Después, abra su navegador y navegue a http://localhost:3000.

Figura 1. Aplicación Starter Express
Starter Express app
Starter Express app

Configure el extremo delantero básico

La aplicación de encuestas usa Framework de bootstrap para la interfaz y configuración del usuario general. Ahora realicemos algunos cambios a la aplicación Express para reflejar esto. Primero, abra routes/index.js y cambie la propiedad del título a Polls:

Listado 1. routes/index.js
 exports.index = function(req, res){ res.render('index', { title: 'Polls' }); };

Después, cambie la plantilla views/index.jade para incluir Bootstrap. Jade es un lenguaje de plantilla de forma corta que se compila a HTML. Use sangrías para remover la necesidad de etiquetas de cierre reduciendo significativamente el tamaño de sus plantillas. Usará Jade para la configuración de la página principal únicamente. Usted usará las plantillas parciales Angular para agregar la funcionalidad a esta página en el siguiente paso.

Listado 2. views/index.jade
 doctype 5 html(lang='en') head meta(charset='utf-8') meta(name='viewport', content='width=device-width, initial-scale=1, user-scalable=no') title= title link(rel='stylesheet', href='//netdna.bootstrapcdn.com/bootstrap/3.0.1/ css/bootstrap.min.css') link(rel='stylesheet', href='/stylesheets/style.css') body nav.navbar.navbar-inverse.navbar-fixed-top(role='navigation') div.navbar-header a.navbar-brand(href='#/polls')= title div.container div

Para ver los cambios a su aplicación, cancele el proceso del servidor de web en Eclipse y corra el archivo app.js de nuevo:

Figura 2. Boilerplate de la aplicación de encuestas

Nota: Al utilizar las plantillas Jade, tenga cuidado de crear las sangrías correctas o tendrá problemas. También evite mezclar estilos de sangrías, dado que Jade mostrará errores si lo intenta.

Paso 2. Diseñe la experiencia del usuario del extremo delantero con AngularJS

Para empezar a usar Angular, primero necesitará incluirlo y agregar algunas directivas dentro de su página HTML. En la plantilla views/index.jade, cambie el elemento html a lo siguiente:
html(lang='en', ng-app='polls').

Dentro del bloque del encabezado en este archivo, agregue los siguientes elementos del guión:

Listado 3. Elementos del guión para cargar el módulo Angular y Angular Resource
 script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js') script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.0.8 /angular-resource.min.js')

Después, cambie el elemento body en la plantilla, agregando un atributo ng-controller (para vincular posteriormente la interfaz del usuario al código de la lógica del controlador):
body(ng-controller='PollListCtrl').

Finalmente, cambie el último elemento div en la plantilla para incluir un atributo ng-view: div(ng-view).

Construya el módulo Angular

De manera predeterminada, Express publica recursos estáticos tales como archivos fuente JavaScript, CSS stylesheets, e imágenes del directorio público en su proyecto. En el directorio público, cree un nuevo subdirectorio designado javascripts. En este subdirectorio, cree un archivo designado app.js. Este archivo contiene el módulo Angular para la aplicación, definiendo las rutas y plantillas que deberá usar para la interfaz del usuario:

Listado 4. public/javascripts/app.js
 angular.module('polls', []) .config(['$routeProvider', function($routeProvider) { $routeProvider. when('/polls', { templateUrl: 'partials/list.html', controller: PollListCtrl }). when('/poll/:pollId', { templateUrl: 'partials/item.html', controller: PollItemCtrl }). when('/new', { templateUrl: 'partials/new.html', controller: PollNewCtrl }). otherwise({ redirectTo: '/polls' }); }]);

Los controladores Angular definen el alcance de su aplicación, proporcionando los datos y métodos para las vistas por vincular.

Listado 5. public/javascript/controllers.js
 // Managing the poll list function PollListCtrl($scope) { $scope.polls = []; } // Voting / viewing poll results function PollItemCtrl($scope, $routeParams) { $scope.poll = {}; $scope.vote = function() {}; } // Creating a new poll function PollNewCtrl($scope) { $scope.poll = { question: '', choices: [{ text: '' }, { text: '' }, { text: '' }] }; $scope.addChoice = function() { $scope.poll.choices.push({ text: '' }); }; $scope.createPoll = function() {}; }

Cree las plantillas parciales de HTML

Para proporcionar datos de los controladores, Angular usa plantillas HTML parciales que le permiten usar marcadores de posición y expresiones para incluir datos y realizar operaciones tales como condicionales e iteradores. En el directorio público, cree un nuevo subdirectorio denominado parciales. Crearemos tres parciales para nuestra aplicación. Este primer parcial desplegará la lista de las encuestas disponibles y usaremos Angular para filtrar fácilmente esta lista mediante un campo de búsqueda.

Listado 6. public/partials/list.html
 <div class="page-header"> <h1>Poll List</h1> </div> <div class="row"> <div class="col-xs-5"> <a href="#/new" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> New Poll</a> </div> <div class="col-xs-7"> <input type="text" class="form-control" ng-model="query" placeholder="Search for a poll"> </div> </div> <div class="row"><div class="col-xs-12"> <hr></div></div> <div class="row" ng-switch on="polls.length"> <ul ng-switch-when="0"> <li><em>No polls in database. Would you like to <a href="#/new">create one</a>?</li> </ul> <ul ng-switch-default> <li ng-repeat="poll in polls | filter:query"> <a href="#/poll/{{poll._id}}">{{poll.question}}</a> </li> </ul> </div> <p> </p>

El segundo parcial permite que el usuario vea la encuesta. Use la directiva del interruptor Angular para determinar si el usuario ha votado. En base a esa determinación desplegará ya sea una forma para votar en la encuesta, o una gráfica con los resultados de la encuesta.

Listado 7. public/partials/item.html
 <div class="page-header"> <h1>View Poll</h1> </div> <div class="well well-lg"> <strong>Question</strong><br>{{poll.question}} </div> <div ng-hide="poll.userVoted"> <p class="lead">Please select one of the following options.</p> <form role="form" ng-submit="vote()"> <div ng-repeat="choice in poll.choices" class="radio"> <label> <input type="radio" name="choice" ng-model="poll.userVote" value="{{choice._id}}"> {{choice.text}} </label> </div> <p><hr></p> <div class="row"> <div class="col-xs-6"> <a href="#/polls" class="btn btn-default" role="button"><span class="glyphicon glyphicon-arrow-left"></span> Back to Poll </div> <div class="col-xs-6"> <button class="btn btn-primary pull-right" type="submit"> Vote »</button> </div> </div> </form> </div> <div ng-show="poll.userVoted"> <table class="result-table"> <tbody> <tr ng-repeat="choice in poll.choices"> <td>{{choice.text}}</td> <td> <table style="width: {{choice.votes.length /poll.totalVotes*100}}%;"> <tr><td>{{choice.votes.length}}</td></tr> </table> </td> </tr> </tbody> </table> <p><em>{{poll.totalVotes}} votes counted so far. <span ng-show="poll.userChoice">You voted for <strong>{{poll.userChoice.text}} </strong>.</span></em></p> <p><hr></p> <p><a href="#/polls" class="btn btn-default" role="button"> <span class="glyphicon glyphicon-arrow-left"></span> Back to Poll List</a></p> </div> <p> </p>

El tercer parcial y final define la forma que le permite al usuario crear nuevas encuestas. Le permite al usuario hacer una pregunta y tres elecciones. Se suministra un botón para permitir que se agreguen elecciones adicionales. Posteriormente, validaremos que el usuario haya introducido al menos dos elecciones — dado que no sería una gran encuesta sin ciertas elecciones.

Listado 8. public/partials/new.html
 <div class="page-header"> <h1>Create New Poll</h1> </div> <form role="form" ng-submit="createPoll()"> <div class="form-group"> <label for="pollQuestion">Question</label> <input type="text" ng-model="poll.question" class="form-control" id="pollQuestion" placeholder="Enter poll question"> </div> <div class="form-group"> <label>Choices</label> <div ng-repeat="choice in poll.choices"> <input type="text" ng-model="choice.text" class="form-control" placeholder="Enter choice {{$index+1}} text"><br> </div> </div> <div class="row"> <div class="col-xs-12"> <button type="button" class="btn btn-default" ng-click= "addChoice()"><span class="glyphicon glyphicon-plus"> </span> Add another</button> </div> </div> <p><hr></p> <div class="row"> <div class="col-xs-6"> <a href="#/polls" class="btn btn-default" role="button"> <span class="glyphicon glyphicon-arrow-left"></span> Back to Poll List</a> </div> <div class="col-xs-6"> <button class="btn btn-primary pull-right" type="submit"> Create Poll »</button> </div> </div> <p> </p> </form>

Finalmente, para desplegar los resultados, necesitamos agregar unas cuantas declaraciones CSS al archivo style.css. Reemplace los contenidos de este archivo con este:

Listado 9. public/stylesheets/style.css
 body { padding-top: 50px; } .result-table { margin: 20px 0; width: 100%; border-collapse: collapse; } .result-table td { padding: 8px; } .result-table > tbody > tr > td:first-child { width: 25%; max-width: 300px; text-align: right; } .result-table td table { background-color: lightblue; text-align: right; }

En este punto, si corre la aplicación, usted verá una lista vacía de encuesta. Si intenta crear una nueva encuesta podrá ver la forma y agregar más elecciones pero no podrá guardar la encuesta. Vamos a concluir todo esto en el siguiente paso.

Paso 3. Almacenar datos en MongoDB usando Mongoose

Para almacenar los datos, la aplicación usa el controlador MongoDB y los módulos Mongoose npm. Esto permite que la aplicación se comunique con una base de datos MongoDB. Para obtener estos módulos, abra el archivo package.json en el directorio raíz de la aplicación y en la sección de dependencias, agregue estas líneas:.

Listado 10. Agregando líneas a la sección de dependencias
 "mongodb": ">= 1.3.19", "mongoose": ">= 3.8.0",

Guarde el archivo, dé clic derecho en Project Explorer y elija Run As > npm install. Esto instalará los módulos npm y cualesquiera dependencias adicionales.

Cree un modelo Mongoose

Cree un nuevo subdirectorio en sus modelos designados de la raíz de su aplicación y en ese subdirectorio cree un nuevo archivo denominado Poll.js. Aquí es donde definiremos nuestro modelo Mongoose, que se usará para consultar y guardar datos a MongoDB de manera estructurada.

Listado 11. modelos/Poll.js
 var mongoose = require('mongoose'); var voteSchema = new mongoose.Schema({ ip: 'String' }); var choiceSchema = new mongoose.Schema({ text: String, votes: [voteSchema] }); exports.PollSchema = new mongoose.Schema({ question: { type: String, required: true }, choices: [choiceSchema] });

Defina las rutas API para el almacenamiento de datos

Después, configure algunas rutas en el archivo app.js en la raíz de su aplicación para crear endpoints JSON que puedan usarse para consultar y actualizar MongoDB desde el código del extremo del cliente Angular. Encuentre la línea app.get('/', routes.index) y agregue el siguiente código después del mismo.:

Listado 12. Cree endpoints JSON
 app.get('/polls/polls', routes.list); app.get('/polls/:id', routes.poll); app.post('/polls', routes.create);

Ahora necesita implementar estas funciones. Reemplace los contenidos del archivo routes/index.js con este código:

Listado 13. routes/index.js
 var mongoose = require('mongoose'); var db = mongoose.createConnection('localhost', 'pollsapp'); var PollSchema = require('../models/Poll.js').PollSchema; var Poll = db.model('polls', PollSchema); exports.index = function(req, res) { res.render('index', {title: 'Polls'}); }; // JSON API for list of polls exports.list = function(req, res) { Poll.find({}, 'question', function(error, polls) { res.json(polls); }); }; // JSON API for getting a single poll exports.poll = function(req, res) { var pollId = req.params.id; Poll.findById(pollId, '', { lean: true }, function(err, poll) { if(poll) { var userVoted = false, userChoice, totalVotes = 0; for(c in poll.choices) { var choice = poll.choices[c]; for(v in choice.votes) { var vote = choice.votes[v]; totalVotes++; if(vote.ip === (req.header('x-forwarded-for') || req.ip)) { userVoted = true; userChoice = { _id: choice._id, text: choice.text }; } } } poll.userVoted = userVoted; poll.userChoice = userChoice; poll.totalVotes = totalVotes; res.json(poll); } else { res.json({error:true}); } }); }; // JSON API for creating a new poll exports.create = function(req, res) { var reqBody = req.body, choices = reqBody.choices.filter(function(v) { return v.text != ''; }), pollObj = {question: reqBody.question, choices: choices}; var poll = new Poll(pollObj); poll.save(function(err, doc) { if(err || !doc) { throw 'Error'; } else { res.json(doc); } }); };

Vincule datos al extremo del frente con los servicios Angular

En este punto, el back-end se configure para habilitar las consultas y guardar las encuestas a la base de datos, pero necesitamos hacer cambios en Angular para que sepa la forma de comunicarse con el mismo. Esto se hace fácilmente usando los servicios Angular, que concluyen el proceso de comunicarse con el lado del servidor en llamadas con una función directa:

Listado 14. public/javascripts/services.js
 angular.module('pollServices', ['ngResource']). factory('Poll', function($resource) { return $resource('polls/:pollId', {}, { query: { method: 'GET', params: { pollId: 'polls' }, isArray: true } }) });

Con este archivo creado, necesita incluirlo en su plantilla index.jade. Agregue esta línea debajo del elemento del último guión en la sección de títulos:
script(src='/javascripts/services.js').

También necesita decirle a su aplicación Angular que use este módulo de servicio. Para hacer esto abra public/javascripts/app.js y cambie la primera línea para que lea lo siguiente:
angular.module('polls', ['pollServices']).

Finalmente, cambie los controladores Angular para usar el servicio para hacer consultas y guardar encuestas en la base de datos. En el archivo public/javascripts/controllers.js, cambie PollListCtrl por esto:.

Listado 15. public/javascripts/controller.js
 function PollListCtrl($scope, Poll) { $scope.polls = Poll.query(); } ...

Actualice la función PollItemCtrl para que haga una consulta de una encuesta por medio de su ID:

Listado 16. public/javascripts/controller.js (continuación)
 ... function PollItemCtrl($scope, $routeParams, Poll) { $scope.poll = Poll.get({pollId: $routeParams.pollId}); $scope.vote = function() {}; } ...

Similarmente, cambie la función PollNewCtrl para que envíe los nuevos datos de la encuesta al servidor cuando se envíe la forma.

Listado 17. public/javascripts/controller.js (continuación)
 ... function PollNewCtrl($scope, $location, Poll) { $scope.poll = { question: '', choices: [ { text: '' }, { text: '' }, { text: '' }] }; $scope.addChoice = function() { $scope.poll.choices.push({ text: '' }); }; $scope.createPoll = function() { var poll = $scope.poll; if(poll.question.length > 0) { var choiceCount = 0; for(var i = 0, ln = poll.choices.length; i < ln; i++) { var choice = poll.choices[i]; if(choice.text.length > 0) { choiceCount++ } } if(choiceCount > 1) { var newPoll = new Poll(poll); newPoll.$save(function(p, resp) { if(!p.error) { $location.path('polls'); } else { alert('Could not create poll'); } }); } else { alert('You must enter at least two choices'); } } else { alert('You must enter a question'); } }; }

Corra la aplicación

¡Ya casi está allí! En este punto la aplicación deberá permitir que los usuarios vean y busquen las encuestas, creen nuevas encuestas y vean las opciones de votación de una encuesta individual. Antes de correr la aplicación, asegúrese de tener a MongoDB corriendo localmente. Esto es típicamente tan simple como abrir una terminal o indicador de comando y correr el comando mongod Asegúrese de dejar la ventana de la terminal abierta en la medida que corra su aplicación:

Figura 3. Visualice las elecciones de encuestas
Viewing a poll's choices
Viewing a poll's choices

Después de que corra la aplicación, navegue a http://localhost:3000 en su navegador y cree unas cuantas encuestas. Si hace clic en una encuesta podrá ser capaz de ver las elecciones disponibles, pero no será capaz de realmente votar en la encuesta o ver los resultados aún. Eso lo cubriremos en el siguiente paso y final.

Paso 4. Votación en tiempo real con Socket.io

La única característica que queda por construir es la funcionalidad de la votación. La aplicación permitirá que los usuarios voten y en la medida que lo hacen se actualizarán los resultados en tiempo real en cualesquiera clientes conectados. Esto se implementa fácilmente usando el modulo socket.io npm, así que hagamos eso ahora.

Abra el archivo package.json en la raíz de su directorio de aplicación y agregue la siguiente sección de dependencias:
"socket.io": "~0.9.16".

Guarde el archivo, dé un clic derecho en Package Explorer y seleccione Run As > npm install para instalar el módulo npm.

Después, abra el archivo app.js en la raíz de la aplicación y quite el bloque server.listen... justo al final del archivo, reemplazándolo con este:

Listado 18. app.js
 ... var server = http.createServer(app); var io = require('socket.io').listen(server); io.sockets.on('connection', routes.vote); server.listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); });

Después, modifique la plantilla index.jade para incluir la biblioteca del cliente socket.io. Cuando se corre la aplicación, esta biblioteca estará disponible automáticamente en la ubicación especificada, por lo que no necesita preocuparse por encontrar este archivo usted mismo. Asegúrese de incluir esto justo después de la línea donde se incluyó la biblioteca de recursos angulares en la plantilla:
script(src='/socket.io/socket.io.js').

Finalmente, necesita crear la función de votos para que se guarde un nuevo voto cuando el usuario envíe un mensaje a socket.io, y de tal manera que entonces se emita un mensaje a todos los clientes con los resultados actualizados. Agregue esto al final del archivo index.js en el directorio de rutas:

Listado 19. routes/index.js
 // Socket API for saving a vote exports.vote = function(socket) { socket.on('send:vote', function(data) { var ip = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address.address; Poll.findById(data.poll_id, function(err, poll) { var choice = poll.choices.id(data.choice); choice.votes.push({ ip: ip }); poll.save(function(err, doc) { var theDoc = { question: doc.question, _id: doc._id, choices: doc.choices, userVoted: false, totalVotes: 0 }; for(var i = 0, ln = doc.choices.length; i < ln; i++) { var choice = doc.choices[i]; for(var j = 0, jLn = choice.votes.length; j < jLn; j++) { var vote = choice.votes[j]; theDoc.totalVotes++; theDoc.ip = ip; if(vote.ip === ip) { theDoc.userVoted = true; theDoc.userChoice = { _id: choice._id, text: choice.text }; } } } socket.emit('myvote', theDoc); socket.broadcast.emit('vote', theDoc); }); }); }); };

Nota: si se pregunta el por qué la aplicación busca el encabezado 'x-forwarded-for' antes de la propiedad de la dirección de IP regular, esto es para asegurar que se use el IP del cliente correcto cuando se despliegue la aplicación en un ambiente con una carga balanceada. Si despliega la aplicación a IBM Cloud o Cloud Foundry, por ejemplo, esto es esencial para que la aplicación funcione correctamente.

Agregue un servicio Angular para enviar datos a los conectores de Web

La funcionalidad de back-end para Web Sockets ahora está completa. Todo lo que queda es vincular el extremo delantero para enviar y escuchar los eventos de los conectores. El mejor enfoque para hacer esto es agregar un nuevo servicio Angular. Reemplace los contenidos del archivo services.js en la carpeta public/javascripts con este código:

Listado 20. public/javascripts/services.js
 angular.module('pollServices', ['ngResource']). factory('Poll', function($resource) { return $resource('polls/:pollId', {}, { query: { method: 'GET', params: { pollId: 'polls' }, isArray: true } }) }). factory('socket', function($rootScope) { var socket = io.connect(); return { on: function (eventName, callback) { socket.on(eventName, function () { var args = arguments; $rootScope.$apply(function () { callback.apply(socket, args); }); }); }, emit: function (eventName, data, callback) { socket.emit(eventName, data, function () { var args = arguments; $rootScope.$apply(function () { if (callback) { callback.apply(socket, args); } }); }) } }; });

Finalmente, necesita editar el controlador PollItemCtrl para poder escuchar y emitir los mensajes de Web Socket para los votos. Reemplace el controlador original con esto:

Listado 21. public/javascripts/controllers.js
 ... function PollItemCtrl($scope, $routeParams, socket, Poll) { $scope.poll = Poll.get({pollId: $routeParams.pollId}); socket.on('myvote', function(data) { console.dir(data); if(data._id === $routeParams.pollId) { $scope.poll = data; } }); socket.on('vote', function(data) { console.dir(data); if(data._id === $routeParams.pollId) { $scope.poll.choices = data.choices; $scope.poll.totalVotes = data.totalVotes; } }); $scope.vote = function() { var pollId = $scope.poll._id, choiceId = $scope.poll.userVote; if(choiceId) { var voteObj = { poll_id: pollId, choice: choiceId }; socket.emit('send:vote', voteObj); } else { alert('You must select an option to vote for'); } }; } ...

Vea el producto final en acción

La aplicación de encuestas ahora está completa. Asegúrese de que siga corriendo mongod y corra la aplicación Node de nuevo en Eclipse. Apunte su navegador en http://localhost:3000 y navegue a una encuesta y vote. Deberá ver el resultado. Para ver las actualizaciones en tiempo real, encuentre su dirección de IP y reemplace localhost con el mismo. Después navegue al mismo usando una diferente máquina o incluso un smartphone o dispositivo de tableta en su red local. Cuando se vota en otro dispositivo, el resultado se mostrará allí y el resultado también se empujará a su navegador de computadora principal automáticamente:

Figura 4. Visualizando los resultados de la encuesta
Viewing poll results
Viewing poll results

Siguientes pasos: desarrollo y despliegue ulteriores

La aplicación de encuestas que acaba de crear es un punto de inicio decente, pero hay mucho por mejorar. Al planear aplicaciones como estas, yo quiero seguir una metodología ágil para definir las historias y épicas del usuario, así como desglosar el proyecto en sprints. Usé DevOps Services para este proyecto, lo cual hace que el desarrollo sea realmente simple manteniendo todo su código fuente y colateral del proyecto reunido en un repositorio hospedado en la nube.

Cuando esté satisfecho con su aplicación, el siguiente paso es compartirlo con el mundo. En el pasado, el desplegar incluso una aplicación simple podría ser un poco como una pesadilla, pero gracias a dios esos días ya terminaron. Usando Cloud Foundry-compatible de IBM En la plataforma IBM Cloud, puede desplegar su aplicación a la nube en minutos con una configuración mínima e incluso menos molestias.

Conclusión

Es un gran momento para ser un desarrollador. Tenemos una abundancia de frameworks y herramientas a su disposición que hacen del desarrollo de grandes aplicaciones no sólo sea más simple y más rápido sino también más placentero. En este artículo, usted aprendió a construir una aplicación usando lo que se refiere como el apilamiento MEAN (Mongo, Express, Angular, Node). Este apilamiento algún día podría sobrepasar al apilamiento LAMP (Linux, Apache, MySQL, PHP) que es sinónimo de simplicidad en lo que respecta al desarrollo y despliegue de la aplicación de Web. Yo, por ejemplo, no puedo esperar.


Recursos para Descargar


Temas relacionados


Comentarios

Inicie Sesión o Regístrese para agregar comentarios.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Cloud computing
ArticleID=994230
ArticleTitle=Construya una aplicación de encuestas en tiempo real con Node.js, Express, AngularJS y MongoDB
publish-date=02262018