Node.js ARQSI 2017/2018
Node.js Desenvolvido por Ryan Dahl em 2009 Plataforma para desenvolvimento de aplicações servidoras utilizando JavaScript Baseado naa Google s V8 JavaScript Engine Desenhado para situações de alta concorrência Sem threads nem lançamento de novos processos Última versão: 6.11.4
MEAN, a full stack MongoDB: base de dados NoSQL (não relacional) Express: server-side web framework Angular: framework de desenvolvimento de aplicações no cliente/browser Node.js: plataforma de desenvolvimento no servidor
O que é que o Node.js pode fazer? Node.js can generate dynamic page content Node.js can create, open, read, write, delete, and close files on the server Node.js can collect form data Node.js can add, delete, modify data in your database
Porquê utilizar Node.js? Operações de I/O sem bloqueios Muitas bibliotecas (módulos) Comunidade muito ativa (IRC, Mailing lists, Twitter, Github) Suportado pelos principais sistemas operativos Uma única linguagem para Frontend e Backend
Porquê utilizar Node.js? Node's goal is to provide na easy way to build scalable network programs.
Casos de sucesso
Node.js vs ASP/PHP Processamento do pedido Node.js elimina a fase da espera continuando, simplesmente, para a tarefa seguinte ASP e PHP Node.js 1 Sends the task to the computer's file system. 1 Sends the task to the computer's file system. 2 Waits while the file system opens and reads the file. 2 Ready to handle the next request. 3 Returns the content to the client. 3 When the file system has opened and read the file, the server returns the content to the client 4 Ready to handle the next request
Node.js Suporta concorrência através do conceito de eventos e callbacks Utiliza funções assíncronas e o padrão observer Existe uma única thread que mantem um ciclo de eventos e, sempre que uma tarefa termina, dispara o evento correspondente que sinaliza a execução da função listener do evento
Tratamento de eventos Criar uma função callback que responde ao evento (criar o listener) var listener1 = function() { console.log('execução da função listener 1. ); } Registar a função callback no emissor do evento para um dado evento on('evento1', listener1) //ou addlistener('evento1', listner1) Quando o emissor emite o evento a função callback é executada eventemitter.emit('evento1');
Exemplo exemplo.js var eventos = require('events'); var eventemitter = new eventos.eventemitter(); var listener1 = function() { console.log('execução da função listener.'); } eventemitter.on('evento1', listener1); eventemitter.emit('evento1'); C:\> node exemplo.js Execução da função listner Fim do Programa. C:\> console.log("fim do Programa.");
Node.js orientado a eventos Uma aplicação servidora Node.js corre num único thread. Embora só possa realizar uma tarefa de cada vez, Node.js é muito eficiente a tratar muitos pedidos simultaneamente, devido à sua natureza orientada a eventos. Se no processamento de um pedido inicia a realização de uma operação mais demorada, o programa retorna e passa para o próximo pedido. Quando a operação mais demorada termina, lança um evento e Node.js continua a processar esse pedido.
Node.js orientado a eventos
Node.js orientado a eventos Threads Lock application / request with listener-workers threads Using incoming-request model multithreaded server might block the request which might involve multiple events Using context switching Using multithreading environments where listener and workers threads are used frequently to take an incoming-request lock Asynchronous Event-driven Only one thread, which repeatedly fetches an event Using queue and then processes it Manually saves state and then goes on to process the next event No contention and no context switches Using asynchronous I/O facilities (callbacks, not poll/select or O_NONBLOCK) environments
Processamento síncrono vs. assíncrono Here is how PHP or ASP handles a file request: 1. Sends the task to the computer's file system. 2. Waits while the file system opens and reads the file. 3. Returns the content to the client. 4. Ready to handle the next request. Here is how Node.js handles a file request: 1. Sends the task to the computer's file system. 2. Ready to handle the next request. 3. When the file system has opened and read the file, the server returns the content to the client. 4. Node.js eliminates the waiting, and simply continues with the next request. 5. Node.js runs single-threaded, nonblocking, asynchronously programming, which is very memory efficient.
Exemplo Sem tratamento de eventos var http = require('http'); http.createserver(function(req,res) { res.writehead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end('<h2> Olá mundo! </h2>'); }).listen(8080); console.log('servidor iniciado em localhost:8080');
Exemplo Com tratamento de eventos var http = require('http'); var server = http.createserver(); server.on('request', function(req,res) { res.writehead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end('<h2> Olá mundo! </h2>'); }); server.listen(8080) console.log('servidor iniciado em localhost:8080');
Node.js Não obstrutivo Todos os recursos e módulos disponibilizados para o Node.js adotam um padrão não obstrutivo para a escrita do código. Código estruturado para que as operações possam ser executadas de forma independente entre si
Exemplo exemplo.js var frase; carregafrase = function (callback) { settimeout(function() { //Simula leitura da frase de uma base de dados. frase = "Minha frase obstrutiva"; callback(); }, 3000) } C:\> node exemplo.js Olá Minha frase obstrutiva C:\> imprimefrase = function () { console.log(frase); } carregafrase(imprimefrase); console.log("olá");
NPM NPM Node Package Manager Repositório online de projetos em código livre para o Node.js (http://www.npmjs.com) Utilitário de linha de comando que interage com o repositório online e permite a instalação, a gestão de versões e de dependências dos módulos C:\ProjectFolder\>npm install uppercase
Requisitos Node.js Download do Node.js em http://nodejs.org Instalar Node.js C:\> node v V6.11.4 Instalar a framework Express Download Visual Studio Code em https://code.visualstudio.com/ Instalar Visual Studio Code C:\> npm install express --save
Primeiro projeto Node.js Criar um diretório para o projeto C:\> mkdir ProjectFolder Executar Visual Studio Code e escolher Open folder Selecionar diretório criado para o projeto
Primeiro projeto Node.js Ficheiro package.json Criado na raiz do diretório do projeto Contem informações sobre o projeto o Nome o Versão o Dependências o Licença o Ficheiro main o Pode ser gerado com o comando npm init C:\ProjectFolder\> npm init
Primeiro projeto Node.js Exemplo de um ficheiro package.json package.json { } "name": "node-api", "main": "server.js", "dependencies": { "body-parser": "~1.0.1", "express": "~4.0.0", "mongoose": "*", "mongoose-id-validator": "^0.4.3" }
Primeiro projeto Node.js Com o package.json definido Instalar módulos referenciados C:\> cd ProjectFolder C:\ProjectFolder\> npm install --save Este comando cria diretório node_modules com as bibliotecas
Primeiro projeto Node.js Os módulos instalados são carregados pelo código recorrendo à função require(<nome do módulo>) Exemplo: Exemplo.js var uc = require('upper-case'); console.log(uc("hello world!")); C:\> node exemplo.js HELLO WORLD C:\>
Primeiro projeto Node.js Módulo HTTP Permite ao Node.js transferir informação com o protocolo HTTP var http = require('http'); Servidor Web O módulo HTTP permite criar um servidor Web (método createserver()) var http = require('http'); //create a server object: http.createserver(function (req, res) { res.write('hello World!'); //write a response to the client res.end(); //end the response }).listen(8080); //the server object listens on port 8080
Cabeçalho HTTP Para que o servidor HTTP envie Código HTML deve ser alterada a propriedade content-type do cabeçalho HTTP Para tal, utiliza-se o método writehead(<status_code>,<header>) O primeiro argumento é o Código HTTP 200 O Segundo, é um objeto contendo o cabeçalho da resposta. var http = require('http'); http.createserver(function (req, res) { res.writehead(200, {'Content-Type': 'text/html'}); res.write('hello World!'); res.end(); }).listen(8080);
Query String Argumento req Objeto, do tipo http.incomingmessage, que representa o pedido do cliente Este objeto possui a propriedade url que armazena a parcela do endereço que segue o nome do domínio. var http = require('http'); http.createserver(function (req, res) { res.writehead(200, {'Content-Type': 'text/html'}); res.write(req.url); res.end(); }).listen(8080);
Query String Outro Exemplo var http = require('http'); var url = require('url ); http.createserver(function (req, res) { res.writehead(200, {'Content-Type': 'text/html'}); var qstring = url.parse(req.url, true).query; var txt = qstring.nome + " " + qstring.idade; res.end(txt); }).listen(8080);
Módulos relevantes Alguns módulos relevantes para o desenvolvimento de aplicações Web em Node.js express framework para desenvolvimento de aplicações Web body-parser middleware para tratamento de JSON e dados cookie-parser processamento de cookies multer middleware para multipart/form-data
RESTFull API com Express ARQSI 2017/2018
Gerar estrutura da aplicação Web (scafolding) C:\> cd folderwithprojects C:\> npm install -g express-generator C:\> express myappname https://expressjs.com/en/starter/generator.html How to structure a Node.js Express project, by Sean McGary on Mar 27, 2016
Criar uma RESTful API Criar o ficheiro server.js com o seguinte código: server.js var express = require('express'); app = express(); port = process.env.port 8080; app.listen(port); console.log('restful API server started on: ' + port);
OO, Database & ODM Model As classes dos objetos de negócio/domínio MongoDB NoSQL, document-centered database Mongoose http://mongoosejs.com ODM: Objet/Document Mapper Biblioteca/framework de abstração de ligação a MongoDB
Definição do Modelo Conexão à base de dados MongoDB var mongoose = require('mongoose'); mongoose.connect('mongodb:'mongodb://localhost/test', { usemongoclient: true }); mongoose modulo que permite a inteação com uma base de dados MongoDB. Disponibiliza funcionalidades de modelação da informação baseadas em esquemas e inclui processos para conversão de tipos de informação, validação e construção de inquéritos.
Definição do Modelo A modelação assenta em esquemas que definem a estrutura da informação var Schema = mongoose.schema; var blogschema = new Schema({ title: String, author: String, body: String, comments: [{ body: String, date: Date }], date: { type: Date, default: Date.now }, hidden: Boolean, meta: { votes: Number, favs: Number } });
Definição do Modelo Os Schema Types são: String Number Date Buffer Boolean Mixed ObjectId Array var schema = new Schema({ name: String, binary: Buffer, living: Boolean, updated: { type: Date, default: Date.now }, age: { type: Number, min: 18, max: 65 }, mixed: Schema.Types.Mixed, _someid: Schema.Types.ObjectId, ofstring: [String], ofnumber: [Number], ofobjectid: [Schema.Types.ObjectId], ofarrays: [[]] ofarrayofnumbers: [[Number]] nested: { stuff: { type: String, lowercase: true, trim: true } } })
Definição do Modelo O relacionamento entre esquemas é feito pelo element ObjectId ( ) var authorschema = Schema({ name : String, stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] }); ( ) ( ) var storyschema = Schema({ author : { type: Schema.Types.ObjectId, ref: 'Author' }, }); ( ) title : String
Definição do Modelo A criação do modelo é responsabilidade do método model() do mongoose var Blog = mongoose.model('blog', blogschema); Model name Schema
Validações Todos os Schema Types possuem funcionalidades de validação de campo obrigatório O tipo Number possui validação de min e max O tipo String possui: enum que permite especificar a lista de valores possiveis para o campo match que permite definer uma expressão regular para validar o valor do campo maxlength e minlength para definir a dimensão máxima e minima do texto
Módulo mongoose-id-validator Plug-in que permite verificar se um documento que refere outro pelo seu ID está a referenciar um documento que, de facto, existe. Não garante coerência da informação Não identifica situações de IDs válidos aquando da inserção e que foram posteriormente removidos É necessário implementa lógica de validação para operações de DELETE Instalação: C:\> npm install mongoose-id-validator
Módulo mongoose-id-validator Utilização: var idvalidator = require('mongoose-id-validator ); var ManufacturerSchema = new Schema({ name : String }); var Manufacturer = mongoose.model('manufacturer', ManufacturerSchema); var CarSchema = new Schema({ name : String, manufacturer : { type: Schema.Types.ObjectId, ref: 'Manufacturer, required: true } }); CarSchema.plugin(idvalidator); var Car = mongoose.model('car', CarSchema);
Módulo mongoose-id-validator Utilização: var ford = new ManufacturerSchema({ name : 'Ford' }); ford.save(function() { var focus = new Car({ name : 'Focus' }); focus.manufacturer = "50136e40c78c4b9403000001"; focus.validate(function(err) { //err.errors would contain a validation error for manufacturer with default message focus.manufacturer = ford; focus.validate(function(err) { //err will now be null as validation will pass }); }); });
Definição do Modelo Esquema documento vs. entidade/tabela desnormalização baseada em DDD vs. normalização o Aggregates + Parent-child vs. Chave estrangeira Operações atómicas de escrita Num documento e numa coleção cf. https://docs.mongodb.com/v3.2/core/data-model-design/
Exemplo do Modelo var mongoose = require("mongoose"); var mongoose_validator = require("mongoose-id-validator"); var departamentoschema = mongoose.schema({ Nome: String, Diretor: {type: mongoose.schema.types.objectid, ref: 'Pessoa'}, Alunos: [{ Aluno: {type: mongoose.schema.types.objectid, ref: 'Pessoa }, Notas: [{ UnidadeCurricular: {type: mongoose.schema.types.objectid, ref: 'UC'}, Nota: Number, Data: Date }] }], }); receitaschema.plugin(mongoose_validator); module.exports = mongoose.model('departamento', departamentoschema);
Routeamento cf. https://developer.mozilla.org/en-us/docs/learn/server-side/express_nodejs/mongoose
Configuração do Roteamento A framework express fornece funcionalidades de roteamento O método Router() permite instanciar e gerir essas funcionalidades var router = express.router(); router.use(function(req, res, next) { console.log('something is happening.'); next(); }); router.get('/', function(req, res) { res.json({ message: 'hooray! welcome to our api!' }); });
Configuração do Roteamento A definição de novas rotas é feita pelo método Route() Este objeto também permite definir os métodos HTTP associados ao roteamento router.route('/tasks').get(todolist.list_all_tasks).post(todolist.create_a_task); router.route('/tasks/:taskid').get(todolist.read_a_task).put(todolist.update_a_task).delete(todolist.delete_a_task); Método de ação do controlador
Cliente REST usando node-rest-client - GET outros métodos e mais detalhes em: https://www.npmjs.com/package/node-rest-client
Autenticação e Autorização ARQSI 2017/2018
Introdução Autenticação: determina que o utilizador é quem diz ser Autorização: determina quem (autenticado) tem acesso a quê Since the HTTP protocol is stateless, this means that if we authenticate a user with a username and password, then on the next request, our application won't know who we are. We would have to authenticate again, and again, and again,... Session-based (server-based) authentication Informação de autenticação é armazenada no servidor em sessões (em memória ou com persistência) Escalabilidade é afetada E ainda Cross-Origin Resource Sharing - CORS e Cross-Site Request Forgery - CSRF (cf. Administração de Sistemas)
e em UML? Token-based authentication 1. User Requests Access with Username / Password 2. Application validates credentials 3. Application provides a signed token to the client 4. Client stores that token and sends it along with every request 5. Server verifies token and responds with data cf. https://scotch.io/bar-talk/the-ins-and-outs-of-token-based-authentication
JWT (JSON Web Tokens) A JSON Web Token has three parts: the crypto information, the payload, and the signature. On the server end the token is verified by re-encrypting the payload with the crypto info and checking to see if it matches the signature. Any change to the payload will negate the signature and invalidate the token. The token is secure because the Salt is only known to the server so resigning a fake token is virtually impossible. cf. https://scotch.io/tutorials/the-anatomy-of-a-json-web-token
Como? Create and verify JWTs C:\> npm install jsonwebtoken --save Encrypt and decrypt password C:\> npm install bcryptjs --save Tutoriais: https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens https://medium.freecodecamp.org/securing-node-js-restful-apis-with-json-web-tokens- 9f811a92bb52 https://github.com/expressjs/express/blob/master/examples/route-middleware/index.js https://github.com/vincezk/authorization
Modelo User Definição da classe modelo user.js user.js var mongoose = require('mongoose'); var Schema = mongoose.schema; module.exports = mongoose.model('user', new Schema({ name: String, password: String, email: String, isadmin: Boolean }) );
Definição das rotas para User Alterar server.js referenciando os novos roteamentos server.js ( ) var UserRoutes = require('./app/routes/userroutes'); app.use('/api/users',userroutes); ( ) Criar as novas rotas em UserRoutes.js UserRoutes.js var express = require('express'); var jwt = require('jsonwebtoken'); var bcrypt = require('bcryptjs ); var UserModel = require('../models/user'); var VerifyToken = require('../auth/verifytoken ); var router = express.router(); ( )
Definição das rotas para User - register Rota /api/users/register UserRoutes.js ( ) router.post('/register',function(req,res){ var user= new UserModel(); user.name = req.body.name; user.password = bcrypt.hashsync(req.body.password,8); user.email = req.body.email; user.isadmin = req.body.isadmin; user.save(function (err){ if(err) return res.status(500).send("there is a problem registering the user."); res.json({message:"user registered!"}); }) });
Definição das rotas para User - register Rota /api/users/register
Definição das rotas para User - login Rota /api/users/login UserRoutes.js ( ) router.post('/login',function (req,res){ UserModel.findOne({email: req.body.email}, function(err,user){ if (err) throw err; if(!user) {res.json({success:false,message:'authentication failed. });} else if(user){ if(!bcrypt.comparesync(req.body.password, user.password)) return res.status(401).send({auth:false,token:null,message: 'Auth failed.'}); else { const payload= {user:user.email}; var thetoken = jwt.sign(payload, 'TheSecret_123456789', {expiresin:86400}); res.json({success:true,message:'enjoy your token!',token:thetoken}); } } }); });
Definição das rotas para User - login Rota /api/users/login
Definição das rotas para User - / Rota /api/users/ UserRoutes.js ( ) function hasrole(useremail, role, func){ UserModel.findOne({email: useremail}, function (err, user){ if (err) throw err; } }) if(!user){ res.json({success: false, message: 'Authentication failed.'}); } else if (user) { func(role === 'administrator' && user.isadmin === true) }
Definição das rotas para User - / Rota /api/users/ UserRoutes.js ( ) router.get('/', VerifyToken, function(req, res){ hasrole(req.user, 'administrator', function (decision) { if (!decision) return res.status(403).send( {auth:false,token: null,message: 'You have no authorization.'} ); else UserModel.find(function (err, users){ if (err) res.send(err); res.json(users); }) }); }) module.exports = router;
Definição das rotas para User - / Rota /api/users/
Middleware VerifyToken.js var jwt = require('jsonwebtoken'); function verifytoken(req, res, next){ var token = req.headers['x-access-token']; if (!token) return res.status(403).send({auth:false,message:'no token provided. }); } jwt.verify(token, 'TheSecret_123456789', function(err, decoded){ if (err) return res.status(500).send({auth:false,message:'failed to authenticate token.'}); req.user = decoded.user; next(); }); module.exports = verifytoken;
Implantação no Azure com VS Code ARQSI 2017/2018
Deploy a Node.js Application to Azure URL: https://code.visualstudio.com/tutorials/nodejs-deployment/getting-started Instalar Microsoft CLI 2.0 for Azure URL: https://aka.ms/installazurecliwindows Na consola: C:\> az login To sign in, use a web browser to open the page https://aka.ms/devicelogin and enter the code XXXXXXXXX to authenticate. Aceder a https://aka.ms/devicelogin e colocar o código obtido na consola
Deploy a Node.js Application to Azure Iniciar sessão no azure com a conta pessoal. É enviado um objeto JSON para a consola com a seguinte estrutura: [ { "cloudname": "AzureCloud", "id": "8oct2f12-8f0a-412e-99f3-e1405333bfb", "isdefault": true, "name": "Microsoft Imagine", "state": "Enabled", "tenantid": "84d32234-9d44-407a-9d64-d0b21be94631", "user": { "name": eu@gmail.com", "type": "user" } } ]
Deploy a Node.js Application to Azure Criar o sítio Web no Azure Criar Resource Group (só necessário na 1ª publicação) A "Resource Group" is essentially a named collection of all our application's resources in Azure. For example, a Resource Group can contain a reference to a website, a database, and an Azure function. C:\> az group create --name myresourcegroup --location westus Nome do grupo Configurar Resource Group para ser o grupo utilizado por omissão C:\> az configure --defaults group=myresourcegroup location=westus West US data center https://azure.microsoft.com/pt-pt/regions/ Criar um App Service Plan para definir os recursos físicos utilizados para a hospedagem (só necessário na 1ª publicação) C:\> az appservice plan create --name myplan --sku F1 Free hosting plan
Deploy a Node.js Application to Azure Criar o sítio Web no Azure O nome escolhido para o sitio Web terá de ser único uma vez que o acesso será feito pelo endereço URL http://nome_escolhido.azurewebsites.net A criação será efetuado pelo comando: C:\> az webapp create --name nome_escolhido --plan myplan --runtime "node 6.10" Tells Azure to use node version 6.10.x when running this application
Deploy a Node.js Application to Azure Deploy do sítio Web Este processo recorre ao git e ao Azure CLI e implica um push do repositório para o Azure. 1. Criar um projeto com ficheiro.gitignore C:\> express --git 2. Copiar o ficheiro.gitignore para a pasta do projeto 3. Executar na pasta do projeto C:\Proj> git init C:\Proj> git add -A C:\Proj> git commit m "Initial Commit"
Deploy a Node.js Application to Azure Deploy do sítio Web 4. Criar um Remote (nome para designar o repositório remoto no Azure) Set set up deploy credentials in Azure C:\Proj> az webapp deployment user set --user-name <user> --password <pass> C:\Proj> az webapp deployment source config-local-git --name <nome_escolhido> { "url": "https://<user>@<nome_escolhido>.scm.azurewebsites.net/<nome_escolhido>.git" } C:\Proj> git remote add azure https://<user>@<nome_escolhido>.scm.azurewebsites.net/<nome_escolhido>.git 5. Fazer o deploy para Azure C:\Proj> git push azure master 6. Inserir as credenciais de deployment criadas em 4.
Deploy a Node.js Application to Azure Publicar alterações efetuadas no sítio Web Com a consola 1. Efetuar commit para o repositório local 2. Publicar fazendo push para o Azure Com o VS Code 1. Abrir o Source Control Manager (SCM) (Ctrl+Shift+G) 2. Especificar uma mensagem de commit e pressionar Ctrl+Enter ou selecionar Commit All no menu 3. Para publicar selecionar a opção Publish Branch no menu 4. Especificar azure no Remote para publicação
Mail ARQSI 2017/2018
SMTP2GO no Node.js Ir a https://www.smtp2go.com/ e carregar no Try SMTP2GO Free para efetuar o registo Ir ao menu de Settings e ao submenu Users (painel esquerdo do site) Nesta janela, dentro do circulo verde temos os dados de ligação ao servidor que serão usados no Node.js
SMTP2GO no Node.js Carregar na opção de Add SMTP User, para criar o utilizador de acesso ao servidor SMTP
Testing NodeJS ARQSI 2017/2018
Testing Node.js application https://scotch.io/tutorials/test-a-node-restfulapi-with-mocha-and-chai
Implantação ARQSI 2017/2018
Implantação em Azure Criar conta em Azure: (email + doc de Fernando Mouta) Tutorial: https://code.visualstudio.com/tutorials/nodejsdeployment/getting-started
Implantação em Heroku
Implantação em OpenShift
Pros Very fluent, you don't have to worry about switching languages when writing code for the client and server. JSON, Your JS objects are JSON, if you are writing web APIs - it's JSON and here's the best part - MongoDB. MongoDB lets you store and retrieve JSON documents. This is a very important factor for me as I develop web APIs for my mobile apps. JS - A dynamically typed language like JS gives you flexibility and has advantages over strongly typed language like Java in some situations. One such situation is writing apps for the Node.js platform. It's fast - JS code is compiled to native code by Chrome's V8 runtime. I find a lot of misleading information on blogs and Youtube videos stating that Node.js is slow because it uses JavaScript. Don't fall for this misguided piece of information ;) NPM - Node package manager makes installing Node modules a breeze. Deployment - It's very very easy to deploy. Deploying Node.js apps on Heroku and Nodejitsu saves tons of developer time.
Cons Callback Hell - Node.js relies heavily on callbacks and you might not be surprised writing nested callbacks which are 5 or 6 levels deep. You could avoid this by using named functions or by using futures and promises. Code structure and maintenance When you are building a large app. There the language itself should be able to enforce constraints over the API design as well as on other developers collaborating on the project. JavaScript as a language lacks this ability. A strongly typed language like Java will aid you in accomplishing this. Although I understand that this could partly be done using an MVC framework like Backbone.js. The language itself is lacking in this area. Testability Java apps are easy to test, this may be due to the fact that I have more experience with testing frameworks in Java. Performance I wrote a couple of basic applications (each app written in express.js and Play 2) and used Apache Bench to load test them. Play outperformed in both the cases. (I did not cluster Node.js during testing so it wasn't using all available cores on my Mac. However Play framework is built on Akka and uses multiple cores when available). Since I was happy with Play's performance, I didn't run Node.js on cluster mode.
Referências https://www.codementor.io/olatundegaruba/nodejs-restful-apis-in-10-minutes-q0sgsfhbd https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4 https://openclassrooms.com/courses/ultra-fast-applications-using-node-js/creating-your-first-app-with-node-js http://mongoosejs.com/index.html https://developer.mozilla.org/en-us/docs/learn/server-side/express_nodejs/mongoose http://mongoosejs.com/docs/schematypes.html
Bibliografia https://pt.slideshare.net/apaichonpunopas/nodejs-for-beginner/11 https://www.w3schools.com/nodejs/default.asp https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4 https://scotch.io/bar-talk/the-ins-and-outs-of-token-based-authentication https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens https://www.tutorialspoint.com/nodejs/index.htm, e em particular: https://www.tutorialspoint.com/nodejs/nodejs_express_framework.htm https://www.tutorialspoint.com/nodejs/nodejs_restful_api.htm https://openclassrooms.com/courses/ultra-fast-applications-using-node-js https://scotch.io/tutorials/test-a-node-restful-api-with-mocha-and-chai https://code.visualstudio.com/docs/nodejs/nodejs-tutorial https://code.visualstudio.com/docs/nodejs/nodejs-debugging https://code.visualstudio.com/tutorials/nodejs-deployment/getting-started
Node.js ARQSI 2017/2018