As 8 dúvidas técnicas mais comuns sobre Node.js

Atualizado em 21/09/2017!

Plataforma nova, dúvidas novas. Como muita gente (inclusive eu) têm começado agora a desenvolver aplicações em Node.js, por diversos motivos que já elenquei em outros posts, é comum que surjam dúvidas uma vez que é uma plataforma bem diferente do que as tradicionais C# e Java que muito de nós programam.

A ideia desse post é elencar as 8 principais dúvidas técnicas sobre Node.js. Caso esteja ainda mais cru do que eu na plataforma, recomendo ler primeiramente estes posts:

As dúvidas que serão respondidas neste artigo são:

  1. Qual a diferença entre til e circunflexo no packages.json?
  2. Como eu depuro programas Node.js?
  3. Qual é o propósito do module.exports e como eu uso ele?
  4. Como faço uso de todos meus processadores?
  5. Como ver completamente os objetos Node.js no console?
  6. Como executar Node.js como um serviço?
  7. Como enviar um email via Node.js?
  8. Como eu posso compartilhar código entre o servidor e o cliente?

Vamos lá!

#1 – Qual a diferença entre til e circunflexo no packages.json?

Então você abre o packages.json e rapidamente entende que as dependencies são os pacotes que sua aplicação usa, mas onde deveriam estar listadas as versões dos pacotes tem um monte de símbolos que não lhe dizem muita coisa…Resumidamente funciona assim:

  • O til garante que o pacote seja sempre carregado  respeitando o número do meio da versão. Ex: ˜1.2.3 pega o pacote mais recente da versão 1.2.x, mas não vai atualizar para 1.3. Geralmente garante que correções de bugs sejam atualizados no seu pacote.
  • O circunflexo garante que o pacote seja sempre carregado respeitando o primeiro número da versão. Ex: ˆ1.2.3 pega o pacote mais recente da versão 1.x, mas não vai atualizar para 2.0. Garante que bugs e novas funcionalidades do seu pacote sejam atualizados, mas não novas versões “major” dele.

A imagem abaixo ajuda a entender o template de versões dos pacotes do NPM, que aliás usa um padrão bem comum da indústria de software:

Outros símbolos incluem:

  • >, >=, <, <=1.0: a versão deve ser superior, superior ou igual, inferior, inferior ou igual à 1.0, respectivamente.
  • 1.2.x: equivalente a ˜1.2.0
  • *: qualquer versão do pacote
  • latest: a versão mais recente do pacote

Agora se você não tiver símbolo algum, aí o pacote deve ser sempre carregado usando a versão especificada.

Uma dica bem valiosa aqui (quem não gosta de um bônus?) para quando se quer atualizar todos pacotes é colocar * na versão de todos e rodar o comando “npm update –save” sobre a pasta do projeto.

#2 – Como eu depuro programas Node.jS?

Assim como o JS tradicional, em Node podemos usar qualquer editor de texto para programar nossas aplicações. No entanto, opções simplificadas demais como Notepad e editores de linha de comando (como nano), embora práticas de usar não são muito úteis quando precisamos depurar aplicações bugadas. Sendo assim, vou dar duas sugestões de como depurar programas Node.js.

Opção 1: troque seu editor de texto. O melhor jeito que eu faço atualmente é usando o Visual Studio Code, que vem com suporte nativo a Node.js. É gratuito e roda em Windows, Mac e Linux. Nele você pode colocar breakpoints em arquivos .js, inspecionar variáveis, testar expressões no console, integração com Git, StandardJS e muito mais. E é uma ferramenta gratuita que roda em Windows e tem uma versão beta pra Mac.

Outra alternativa, mais pesada é o  Visual Studio Community (2015 com plugin para Node ou 2017 com suporte nativo). Eu usava antes, mas não não uso mais.

Opção 2: use um depurador externo ao seu editor. Agora se você não quer abrir mão de usar editores de texto nativos do seu SO ou os mais clássicos que você já está acostumado, tem algum tempo que você pode depurar seus programas Node.js diretamente no Google Chrome também, usando o F12. Você consegue mais informações neste post do Medium.

E por fim, uma outra alternativa para não largar seus editores de texto favoritos é usando o Node Inspector, um projeto open-source disponível no GitHub.

#3 – Qual é o propósito do module.exports e como eu uso ele?

Nos tutoriais simples que eu tenho aqui no blog de como programar usando Node.js com MongoDB eu sempre recomendo criar um arquivo JS db.js com a lógica de conexão do banco de dados. Ao final do arquivo, sempre vemos um modulo.exports que recebe um objeto JSON. Mais tarde, damos um require nesse db.js pra poder usar a conexão internamente criada nele. Mas final, o que o module.exports faz?

Resumidamente, module.exports define qual objeto deste arquivo JS será exportado (ou exposto) quando uma chamada require for feita à ele. Ele é um análogo ao return do arquivo JS como um todo.

Um atalho do Node permite que você use apenas a palavra exports ao invés de module.exports.

Um exemplo de uso bem comum é para criar uma biblioteca de funções dentro de um arquivo JS que precisa ser chamada por outros arquivos JS. Considere o seguinte arquivo mymodule.js:

Aqui expusemos as funções myFunc1 e myFunc2. Se quisermos usar essas funções em outro arquivo, basta usarmos o require, como abaixo:

#4 – Como faço uso de todos meus processadores?

O Node.js trabalha com uma única thread dentro de um único processo na sua máquina. Dessa forma, é natural que ele utilize apenas um processador, mesmo que você esteja rodando sua aplicação em um webserver com 16 núcleos ou mais. Sendo assim, uma dúvida bem comum é: como escalar um projeto Node para que use todo o poder do seu servidor?

Basicamente você tem duas opções:

Opção 1: usar uma arquitetura de micro-serviços. Cada módulo da sua aplicação deve ser uma sub-aplicação autônoma, que responde a requisições e realiza apenas as tarefas que são sua responsabilidade. Sendo assim, teríamos diversas aplicações pequenas escritas em Node.js, cada uma usando um core da sua máquina e recebendo (e processando) as requisições que lhe cabem. Uma aplicação principal recebe a requisição original do usuário e delega as tarefas para as demais sub-aplicações.

Opção 2: usar um webproxy na frente do Node. Você pode colocar um Apache, Nginx ou IIS à frente da sua aplicação e deixar com ele essa tarefa de controlar a carga de requisições, balanceando entre diferentes nós idênticos da sua aplicação, cada um em um processador. Você pode fazer isso com Node.js também, mas geralmente Apache e cia. já possuem muito mais maturidade pra isso.

Existem outras opções? Sim. No entanto, as duas que recomendo estão acima.

Curso Node.js e MongoDB
Curso Node.js e MongoDB

#5 – Como ver completamente os objetos em NodeJS no console?

Certas vezes quando temos objetos complexos em Node.js e queremos ver o que ele está guardando dentro de si usamos o console do Google Chrome ou mesmo do Visual Studio para entender o que se passa com nosso objeto. No entanto, dependendo do quão “profundo” é o nosso objeto (quantos objetos ele possui dentro de si), essa tarefa não é muito fácil.

Aqui vão algumas formas de imprimir no console o seu objeto JSON inteiro, não importando quantos níveis hierárquicos ele tenha:

Opção 1: console.log. Tente usar a função console.log passando o objeto or parâmetro, isso funciona na maioria dos casos.

Opção 2: util.inspect. Use o seguinte código abaixo para usara  função util.inspect e retornar todo o conteúdo de um objeto JSON.

Opção 3: JSON.stringify. Use a função JSON.stringify passando o objeto e o nível de identação que deseja dentro do objeto, como abaixo.

#6 – Como executar Node.js como um serviço?

Para quem escolher rodar suas aplicações Node.js em ambiente Windows, existe uma série de passos necessários para que funcione correta e ininterruptamente, que já abordei nesse post aqui, inclusive no Passo 6 eu ensino como instalar seu app Node como se fosse um Windows Service.

#7 – Como enviar um email via Node.js?

Este é um problema bem comum para quem quer fazer coisas simples como um formulário de contato em uma aplicação web. Algo tão trivial em linguagens como PHP se torna uma dor de cabeça em Node. Claro, não estou falando de envio massivo de emails, que nunca deve ser feito usando SMTPs tradicionais (como o da sua conta de email) e sim com serviços de SMTP Gateway como Sendgrid e Mandrill. Estou falando de envios pontuais.

Existem algumas bibliotecas em Node que prometem resolver esse problema para você. Algumas oferecem suporte a contas Gmail,outras não, mas em geral todas funcionem em menor ou maior grau com os padrões atuais de envio de email. Elas são (em ordem de relevância):

  • Nodemailer: a primeira opção, focada no envio dos emails e não na personalização dos mesmos. Muito popular desde 2010, quando hão havia opção alguma na plataforma para envio de emails. Em menos de 2 minutos você tem ele funcionando e enviando emails.
  • Node Email Templates:  O pacote mais completo da Internet para envio de emails via Node.js. Permite construir mensagens agradáveis usando a sua view engine e pré-processadores CSS. É um projeto ativo com atualizações frequentes no Github, mas um pouco complexo para quem está começando.
  • EmailJS: para quem tem problemas com anexos no Nodemailer, esse aqui é o pacote ideal, no mais, Nodemailer é melhor.
  • AlphaMail: uma solução completa “as-a-Service” onde você dispara emails usando a infraestrutura da AlphaMail mesmo. Não sei o quão bom os caras são no envio de emails, mas me pareceu muito simples e particularmente útil para quem não quer se preocupar com SMTP e coisas do gênero.

Para não ficar apenas indicando bibliotecas,a qui vai um código JS de envio de email usando Nodemailer, o mais recomendado dentre os pacotes citados, usando como SMTP a minha hospedagem na Umbler (você pode criar uma conta gratuita lá e usar os créditos para criar uma conta de email):

#8 – Como eu posso compartilhar código entre o servidor e o cliente?

Muitas pessoas chegam até o Node com a promessa de escrever tanto o client-side quanto o server-side na mesma linguagem. No entanto, para que realmente isso seja vantajoso tem de ser possível o reuso de software em ambos os lados da aplicação, certo?!

Eu vou mostrar aqui uma forma de conseguir reutilizar os seus módulos JS tanto no browser quanto no Node.js.

Primeiramente, em Node quando queremos expor um módulo, usamos um código semelhante a esse:

No entanto, no browser isso dá erro uma vez que exports é undefined neste ambiente. Sendo assim, para contornar este problema, o primeiro passo é verificar a existência ou não do exports, caso contrário, teremos que criar um objeto para o qual possamos exportar as funções:

O problema com essa abordagem, é que no browser as funções que não foram exportadas também ficam disponíveis como funções globais, o que não é algo desejável. Resolvo isso usando closures, como no exemplo abaixo:

O uso do objeto this representa o browser, e o uso de this[‘mymodule’] é o local de exportação no browser. Esse código está pronto para ser usado tanto no browser quanto no server. Considerando que ele está em um arquivo mymodule.js, usamos esse módulo da seguinte maneira em Node:

E no browser usamos assim:

Claro, existem códigos JS escritos em Node que não serão suportados pelo browser, como o comando require por exemplo. Sendo assim, os módulos compartilhados entre os dois terão de ser o mais genéricos possíveis para que haja compatibilidade.

Também tome cuidado com as features mais recentes da linguagem Javascript que muitas vezes são suportadas pela engine V8 que o Node usa mas não pelos demais browsers.

Até a próxima!

Curtiu o post? Então clica no banner abaixo e dá uma conferida no meu livro sobre programação web com Node.js!

O que achou desse artigo?
[Total: 4 Média: 3.3]

Publicado por

Luiz Duarte

Pós-graduado em computação, professor, empreendedor, autor, Agile Coach e programador nas horas vagas.