Introdução ao Node.js

Node.js é um runtime (ambiente) utilizado para executar aplicações JavaScript. Neste cenário, além de oferecer um ambiente multiplataforma, recursos são disponibilizados para apoiar na implementação de aplicações (https://nodejs.org/en/docs/).

Criado por Ryan Dahl em 2009, Node.js é baseado na engine V8, desenvolvida pela Google e usada no Google Chrome. Neste cenário, o Node.js se preocupa em ofertar um ambiente de execução, enquanto que a engine V8 se preocupa com a interpretação do código JavaScript.

Neste ponto, é importante conhecer a relação entre JavaScript e ECMAScript (ES). ECMAScript é uma especificação de linguagem de script, usada por exemplo pelo JavaScript e ActionScript (Flash). Dessa forma, JavaScript é uma linguagem que implementa a especificação ECMAScript. Porém, existem diferentes versões da ECMAScript. Por fim, diferentes engines de JavaScript implementam diferentes versões da ECMAScript. Confira os recursos ECMAScript implementados e disponíveis em cada versão do Node.js (https://node.green/).

Uma característica atribuída ao Node.js diz respeito à escalabilidade de aplicações, onde recomenda-se seu uso para o desenvolvimento de APIs, aplicações de tempo-real, etc. Porém, os principais diferenciais do Node.js estão relacionados à sua arquitetura baseada em eventos (Event-Loop), bem como ao I/O não bloqueante que tem foco em tarefas assíncronas. Por fim, Node.js trabalha por meio de single-thread, porém, o uso de clusters por meio de pacotes específicos pode otimizar CPUs de múltiplos núcleos.

Este artigo tem como objetivo apresentar os principais benefícios do Node.js, bem como abordar algumas boas práticas e pacotes interessantes para o desenvolvimento de aplicações.

Principais benefícios

Quando desenvolvemos com Node.js utilizamos uma abordagem orientada a eventos, o que exige identificar/mapear/generalizar quais eventos podem ocorrer, bem como disponibilizar uma interface para ouvi-los, possibilitando executar operações específicas.

Estar melhor preparado para trabalhar com interações de tempo real entre cliente e servidor é um diferencial interessante do Node.js. Neste ponto, destacam-se os pacotes SockJS, Socket.IO e Engine.IO. Estes pacotes são compatíveis com o protocolo WebSockets e permitem trafegar dados por meio de uma conexão bi-direcional, tratando as mensagens via eventos no JavaScript.

Por ser uma linguagem single-threaded, o JavaScript acaba tendo benefícios (e.g., ausência de deadlocks), mas também existem limitações quando executamos blocos de códigos demorados. Neste ponto, é essencial analisar possíveis gargalos no código e refatorar visando tarefas assíncronas.

Para instalar o Node.js, acesse o site https://nodejs.org/.

Gerenciamento de pacotes com NPM

NPM é um gerenciador de pacotes para código JavaScript. Trata-se de um facilitador para reutilização de código compartilhado, onde pequenos pacotes são criados para solucionar problemas específicos. Dessa forma, desenvolvedores e engenheiros de software ficam responsáveis pela composição de soluções customizadas, combinando diferentes pacotes. Porém, dependências externas são perigosas e continua sendo necessário analisar o que está sendo adotado, bem como o envolvimento da comunidade e a disponibilidade de documentação do pacote.

Neste cenário, é importante conhecer as formas de instalar pacotes na aplicação (e.g., local e global). Quando o uso do pacote se limitar no apoio ao desenvolvimento de forma externa, este deve ser instalado de forma global. Por outro lado, caso o pacote faça parte do projeto, uma dependência para que os requisitos do projeto sejam realizados, este deve ser instalado localmente.

// Global
npm install -g swagger

// Local
npm install express --save

O gerenciamento dos pacotes instalados localmente na aplicação ocorre por meio do arquivo package.json, que organiza informações sobre o projeto, suas dependências e scripts visando a inicialização da aplicação, etc.

Para descobrir pacotes ou obter mais informações, acesse o site https://www.npmjs.com/.

Boas práticas usando Node.js

  • Instalar versão estável do Node.js (LTS);
  • Compreender o versionamento de pacotes (Major, Minor e Patch);
  • Pesquisar pacotes antes de implementar soluções específicas;
  • Padronização do código e nomenclatura de arquivos;
  • Considerar adoção de guia de estilo de código;
  • Trabalhar de forma assíncrona (promise, async/await, …).

Gerenciamento de erros e processos

Colocar uma aplicação Node.js em produção exige alguns cuidados. Os principais estão relacionados ao gerenciamento de erros e exceções, bem como o gerenciamento automatizado de processos.

Quando ocorrem exceções ou rejeições não tratadas (uncaughtException ou unhandledRejection), o comportamento de uma aplicação Node.js torna-se imprevisível. Neste cenário, uma prática realizada pelos desenvolvedores é armazenar o log do erro/disparar email e finalizar o processo da aplicação para reiniciá-lo. Porém, o gerenciamento de processo da aplicação precisa ser automatizado, neste ponto, destacam-se os pacotes PM2 e Forever.

Existe muita discussão na comunidade sobre o gerenciamento de erros e exceções em aplicações Node.js, porém, não é uma boa prática manter uma aplicação Node.js após um erro crítico ser disparado. O uso dos eventos uncaughtException e unhandledRejection é bastante questionado, porém, na prática continua sendo utilizado para encerrar o processo da aplicação. Por fim, cabe aos desenvolvedores realizarem o tratamento em nível de código (try/catch, promise, etc).

Para mais informações, confira as dicas do framework express (http://expressjs.com/pt-br/advanced/best-practice-performance.html).

Pacotes interessantes

Pacote Descrição
standardjs Guia de estilo JavaScript, com analisador e fixador de código automático.
dotenv Pacote para carregar variáveis de ambiente.
socket.io Framework para criação de aplicações de tempo real.
swagger Pacote composto por ferramentas para projetar e criar APIs.
express Framework minimalista para desenvolvimento de aplicações web.
helmet Pacote de apoio para proteção de aplicações web.
sequelize ORM para Node.js (Banco de dados relacionais).
mongoose ODM para Node.js (MongoDB).
winston Pacote para armazenar log assíncrono.
morgan Pacote para armazenar log de requisição HTTP.
supertest Pacote para teste em alto nível de requisições HTTP.
mocha Pacote para teste unitário.

Confira as listas Awesome mantidas por alguns colaboradores:

Conclusão

Node.js está conquistando muitos desenvolvedores, mas ainda existe debate sobre quando adotá-lo. Não existe bala de prata, continua sendo importante analisar os requisitos funcionais e não funcionais de cada projeto, bem como questões sobre capacitação dos desenvolvedores para construção e manutenção de aplicações. Reconhecer os limites de cada tecnologia bem como os principais cenários para sua aplicação é importante para evitar qualquer tipo de viés, seja gerencial ou técnico.

  • Gabriel "Barbarize" Corrêa

    15/01/2018 às 18:29

    Boa garoto!

Deixe uma resposta

O seu endereço de e-mail não será publicado.. Campos obrigatórios são marcados com *