20 cosas

CUANDO EMPECÉ

que me hubiera gustado saber sobre

(... pero me dABA miedo preguntar)

1. ¿CÓMO FUNCIONA NODEJS?

2. ¿CÓMO TRABAJA EL COMPILADOR V8?

WASM

GC

Liftoff

Orinoco

2. ¿CÓMO TRABAJA EL COMPILADOR V8?

node --print-bytecode app.js

3. ¿CÓMO FUNCIONA EL EVENT LOOP?

refs > 0
refs == 0

4. ¿CÓMO DEPURAR APLICACIONES NODE?

Chrome DevTools

node --inspect=0.0.0.0:9229 server.js

4. ¿CÓMO DEPURAR APLICACIONES NODE?

NDB

// Instalado como dependencia local
npm install --save-dev ndb

// Use ndb en lugar del comando 'node'
ndb server.js

// Si usa algún otro binario
// simplemente anteceder con `ndb` 
ndb npm run unit
 
// Depurar algún paquete instalado globalmente 
ndb mocha
 
// Para usar un binario local,
// use `npx` y anteceda ndb a él 
ndb npx mocha

// Lanzar ndb como aplicación principal
// y luego depurar algún script del
// package.json, e.g. unit tests
ndb .

5. ¿CÓMO HACER LOGGING?

  • Usar un logger maduro y configurable (Morgan, etc.)
     
  • Agregar un transactionId a cada petición para facilitar la trazabilidad y el rastreo.
     
  • Agregar un "sanitizer" para evitar registrar información sensible.

6. MANTENIMIENTO EN PRODUCCIÓN

Crear un endpoint (asegurado) de mantenimiento en producción para:

  • Cambiar el nivel de log sin reiniciar.
  • Generar un "heapdump".
  • Exponer indicadores de salud de la aplicación.
  • Correr scripts de diagnóstico o migración de bases de datos.
  • Retornar estadísticas básicas de monitoreo (a menos de que se usen herramientas que se integren directamente en Node, como N|Solid, etc.)

7. CORRIENDO EL SERVIDOR

En desarrollo:

npm install -g nodemon

nodemon ./server.js localhost 8080

nodemon --watch app app/server.js

En producción:

npm install -g pm2

// Fork mode
pm2 start app.js --name my-api

// Cluster mode (max instances)
pm2 start app.js -i 0 

pm2 monit
pm2 list
pm2 stop 0
pm2 restart 0
systemd

👌🏻!!!

8. OPTIMIZACIONES EN PRODUCCIÓN

  • Delegar tareas como gzip o SSL a un proxy reverso como Nginx.
     
  • Hacer que NodeJS no tenga que suplir assets estáticos, usar CDNs o AWS S3 para éstos.
     
  • Establecer el entorno de Node en producción para recibir optimizaciones de algunos paquetes.
// start.sh
NODE_ENV=production pm2 start index.js

9.                   +                       

npm install --save-dev ts-node

npx ts-node

// También hay una versión de jasmine con TS
npm install --save-dev jasmine-ts


Tip: Cuando se use un transpilador, también subir el código JS resultante al repo para evitar el primer build.

10.                  ++

// Instalar "package"
npm i package
npm i package --verbose    // Más información

// Correr "npm test"
npm t

// Atajo para --save-prod (Antes de v.10 era -S)
npm i react -P

// Atajo para --save-dev
npm i morgan -D

// Buscar en el repositorio
npm search lodash

// Listar paquetes globales
npm ls -g depth=0 

// "Podar" paquetes huérfanos
npm prune

11.                  ++ (scripts)

Anteceder "pre" o "post" a cualquier script común
o personalizado es válido:

"scripts": {
  "preinstall": "node prepare.js",
  "postintall": "node clean.js",
  "build": "webpack",
  "postbuild": "node index.js",
  "postversion": "npm publish",
  "myscript": "node myscript.js",
  "postmyscript": "node clean.js"
}

12.  MODULARIZACIÓN

CommonJS:

// In circle.js
const PI = Math.PI;

exports.area = (r) => PI * r * r;

exports.circumference = (r) => 2 * PI * r;

// In some file
const circle = require('./circle.js');
console.log( `The area of a circle of radius 4 is ${circle.area(4)}`);

12.  MODULARIZACIÓN

ES Modules

//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
System.import('some_module')
      .then(some_module => {
          // Use some_module
      })
      .catch(error => {
          // ...
      });

Dynamic Loading

ADVERTENCIA: característica experimental de la v.12

// package.json
{
  "type": "module"
}

// En la misma carpeta 
// del package.json correr
node --experimental-modules my-app.js

12.  MODULARIZACIÓN

SystemJS

    <script src="system.js"></script>
    <script>
      // Configurar la ruta de referencia baseURL
      System.config({
        baseURL: '/app',
        // o 'traceur' o 'typescript'
        transpiler: 'babel',
        // o traceurOptions o typescriptOptions
        babelOptions: {

        }
      });

      // Carga /app/main.js
      System.import('main.js');
    </script>

Soporta todos los tipos de módulos: CommonJS, AMD y ES 2015

13.  ESTRUCTURA DE ARCHIVOS

  • Reutilizar y distribuir utilidades comunes como paquetes de NPM.
      
  • Requerir los módulos por carpeta, en lugar de directamente por archivo, usado un index.js.
     
  • Es recomendable requerir/importar los módulos al comienzo del archivo, para identificar las dependencias de manera más rápida.

14.  EL MARAVILLOSO MUNDO DE

  • Los tipos primitivos de JS y la cláusula new.
  • Mutabilidad: quizás no necesites ImmutableJS.
  • El caprichoso NaN.
  • Funciones como parámetros.
  • Problemas con separación de líneas.
  • Los riesgos de la coerción.
  • Rarezas por fuera de modo estricto.

15.  COMUNICACIONES EN TIEMPO REAL

PRIMUS

  • Abstrae varios real-time frameworks.
     
  • Reconexión incorporada.
     
  • Detección de modo offline y reconexión.
     
  • Mejora algunos comportamientos de socket.io y ws.
     
  • Primus.io (un fork) proporciona aún más opciones.

No hay ports estables para la mayoría de lenguajes de tipado fuerte (C#, Java)

Modularizar la librería para el cliente es un tema que posee una complejidad importante.  

16.  SOPORTAR VARIAS VERSIONES DE NODE

n:

nvm:

  • Se instala como un paquete de npm.
  • Mueve los archivos de node a la carpeta de trabajo.
  • Tiene un port a windows.
  • Es más compatible con personalizaciones de línea de comando como oh-my-zsh.
  • Puede tener configuraciones específicas por medio de un archivo .nvmrc

17.  SOPORTAR MÚLTIPLES REPOSITORIOS

nrm

npm install -g nrm

nrm ls

/* Output:

* npm -----  https://registry.npmjs.org/
  cnpm ----  http://r.cnpmjs.org/
  taobao --  https://registry.npm.taobao.org/
  nj ------  https://registry.nodejitsu.com/
  skimdb -- https://skimdb.npmjs.com/registry

*/

nrm use cnpm  //switch registry to cnpm

18.  OPTIMIZACIÓN DE EVENTOS

19.  PARALELISMO

  • spawn()
  • fork()
  • exec()
  • execFile()
  • worker threads

20.  TIPS DE SEGURIDAD

  • Guardar secretos en archivos de configuración por fuera del repo o variables de entorno.
  • Usar ORM/ODM para evitar inyección (No, tu lógica no es suficiente, créeme).
  • Asegurar las cabeceras (helmet) para prevenir suplantación o "forging".
  • Validar los esquemas JSON entrantes (jsonschema/joi).
  • Soportar una lista negra de JWTs.
  • Prevenir ataques de fuerza bruta sobre puntos de autenticación
    (Captcha | Tiempo exponencial | Deshabilitar IP a partir de un número determinado de intentos fallidos).
  • Ejecutar el proceso de NodeJS como un usuario no-root.
  • Limitar el tamaño del cuerpo de mensaje recibido usando un middleware o reverse-proxy.
  • npm audit

REFERENCIAS

Made with Slides.com