Event Loop, Módulos e Gerenciamento de Pacotes
Aula 1 de 7
Node.js Runtime
Node.js é um runtime JavaScript baseado no motor V8 do Chrome. Ele permite executar JavaScript no servidor com acesso ao sistema de arquivos, rede e processos.
const os = require('os');
console.log('Platform:', os.platform());
console.log('CPUs:', os.cpus().length);
console.log('Memory:', os.totalmem() / 1024 / 1024 / 1024, 'GB');
Event Loop
O event loop é o coração do Node.js. Ele gerencia operações assíncronas em um modelo single-thread non-blocking.
// Fases do event loop: timers -> pending -> idle/prepare -> poll -> check -> close
console.log('1 - Síncrono');
setTimeout(() => console.log('2 - Timers (setTimeout)'), 0);
setImmediate(() => console.log('3 - Check (setImmediate)'));
process.nextTick(() => console.log('4 - nextTick (antes da próxima fase)'));
Promise.resolve().then(() => console.log('5 - Microtask (Promise.then)'));
console.log('6 - Síncrono');
// Ordem: 1, 6, 4, 5, 2, 3
Microtasks vs Macrotasks
- Microtasks:
process.nextTick,Promise.then/catch/finally - Macrotasks:
setTimeout,setInterval,setImmediate, I/O callbacks
// nextTick tem a maior prioridade entre microtasks
process.nextTick(() => console.log('nextTick 1'));
process.nextTick(() => console.log('nextTick 2'));
Promise.resolve().then(() => console.log('Promise 1'));
// nextTick sempre executa antes de qualquer Promise
Módulos: CommonJS vs ES Modules
CommonJS (padrão no Node.js)
// math.js
const sum = (a, b) => a + b;
const sub = (a, b) => a - b;
module.exports = { sum, sub };
// ou: exports.sum = sum;
// index.js
const { sum, sub } = require('./math.js');
console.log(sum(5, 3)); // 8
ES Modules (moderno)
// package.json
{
"type": "module"
}
// math.mjs
export const sum = (a, b) => a + b;
export const sub = (a, b) => a - b;
// index.mjs
import { sum, sub } from './math.mjs';
console.log(sum(5, 3)); // 8
Diferenças
| Aspecto | CommonJS | ES Modules |
|---|---|---|
| Carregamento | Síncrono | Assíncrono |
| Syntax | require/module.exports | import/export |
| Top-level await | Não | Sim |
__dirname | Disponível | import.meta.url |
// ES Modules: obter __dirname
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
npm e Yarn
# Inicializar projeto
npm init -y
# ou
yarn init -y
# Instalar dependências
npm install express
npm install -D typescript
npm install -g nodemon # global
# yarn
yarn add express
yarn add -D typescript
nvm (Node Version Manager)
# Instalar versões
nvm install 18
nvm install 20
# Usar versão
nvm use 20
# Versão padrão
nvm alias default 20
package.json Scripts
{
"name": "meu-projeto",
"version": "1.0.0",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js",
"test": "jest",
"lint": "eslint src/",
"build": "tsc",
"prestart": "npm run build"
}
}
npm run dev
npm test
npm run lint
Lab: Exercício - Servidor com módulos e scripts
Crie um servidor HTTP modular com scripts npm:
// src/server.js
const http = require('http');
const { getTimestamp } = require('./utils.js');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
message: 'Servidor rodando!',
timestamp: getTimestamp()
}));
});
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Servidor rodando na porta ${PORT}`);
});
// src/utils.js
const getTimestamp = () => new Date().toISOString();
const formatDate = (date) => date.toLocaleDateString('pt-BR');
module.exports = { getTimestamp, formatDate };
{
"scripts": {
"start": "node src/server.js",
"dev": "node --watch src/server.js"
}
}
# Testar o servidor
npm start
O event loop do Node.js prioriza
process.nextTickacima de Promises, e Promises acima de timers. Módulos CommonJS são síncronos, ES Modules são assíncronos com suporte a top-level await.