Arquitetura do Node.js: conheça seus componentes
Introdução
Quando ouvimos falar pela primeira vez em Node.JS, normalmente pensamos que ele foi criado para fazer o trabalho do navegador de interpretar o JavaScript; também temos a impressão de que se trata de um programa “único”, que apenas lê arquivos .js
e retorna seus resultados no terminal.
Na verdade o Node.js faz muito mais do que isso, e longe de ser um programa só, é composto por várias APIs e bibliotecas. Neste artigo apresentaremos quais são os componentes do Node.js, outras tarefas que o Node.js faz, além de interpretar código JavaScript, e quais as responsabilidades de cada parte no todo.
Bora lá?
Os componentes do Node.js
Como falamos acima, quando falamos de JavaScript fora do ambiente do navegador, nos referimos apenas ao Node.js como se fosse uma única ferramenta. Porém, “por baixo dos panos”, o Node.js é composto por algumas bibliotecas e partes separadas, que precisamos conhecer para entender melhor alguns conceitos importantes para o Node.js, como assincronicidade, threads e callbacks.
A imagem acima mostra a estrutura do Node.js e seus componentes internos:
Core API (“API essencial”) do JavaScript, responsável pela implementação do Node.js em alto nível;
C++ bindings, responsáveis por englobar e expor bibliotecas e métodos em C++ que são utilizados através do Node.js;
V8, o motor de execução que faz com que o Node.js consiga compreender o código escrito em JavaScript. Escrito em C++, V8 recebe uma string de código em JavaScript, interpreta e executa. É onde se encontra a implementação da maior parte das funções e métodos JavaScript;
libuv, uma das principais partes que compõem o Node.js. É uma biblioteca escrita em C++ que faz a parte de manipulação de eventos e o manejo de processos assíncronos como timers e funções. Esta lib dá acesso do Node.js ao sistema operacional, ao sistema de arquivos (o conhecido
fs
- file system), conexões e etc. Além disso, delega a execução de algumas partes do programa ao sistema operacional, caso necessário. A libuv também implementa duas funcionalidades muito importantes: o loop de eventos e a thread pool;Outras APIs como
http-parser
,zlib
,openSSL
ec-ares
, que fazem parte do ambiente Node.js mas não fazem parte da V8.
A maior parte do processamento do código é resolvida pelo loop de eventos, como executar callbacks e processos de rede. A thread pool é responsável por tarefas que exigem mais processamento, como acesso, processamento e conversão de arquivos. Para saber mais sobre o loop de eventos e thread pool, explicamos estas partes em detalhe nesse artigo.
Conclusão
O Node.js age como um controlador, “amarrando” juntos V8 e libuv e fornecendo a API para que possamos acessar todas as funcionalidades acima usando JavaScript. Da mesma forma que um controlador, o Node.js “recebe” o código em JavaScript, chama as bibliotecas responsáveis por executar cada parte do código e retorna o resultado final. Podemos pensar em uma camada de abstração final sobre, por exemplo, algumas funções em C++ que o Node.js utiliza.
Quando tudo funciona bem, podemos seguir com nossos códigos sem nos preocupar muito. Porém, quando bugs e efeitos colaterais inesperados acontecem, vale a pena entender melhor o funcionamento de ferramentas como o Node.js e como nossos programas são executados.
Ainda temos bastante assunto sobre o Node.js e sua arquitetura para explorar! Você pode continuar a leitura do próximo tópico, sobre threads e processos.