Gestión de dependencias

Este documento define las prácticas recomendadas para gestionar dependencias en proyectos JavaScript/TypeScript en todo el ecosistema de Decentraland. Se aplica a front-end, back-end, SDKs, bibliotecas compartidas y a cualquier paquete basado en npm/yarn/pnpm.

Resumen:

  • Estrategia de versiones → Usar versiones exactas/fijas para dependencies (seguridad) y devDependencies (entorno de desarrollo consistente). Usar rangos de versión solo para peerDependencies (flexibilidad).

  • Excepción → Los paquetes de Decentraland (@dcl/*, decentraland-*) pueden usar rangos de versión (^) ya que son paquetes internos de confianza.

  • Bibliotecas/paquetes compartidos → Usar peerDependencies con rangos de versión (^) para bibliotecas compartidas (React, @dcl/schemas, etc.). Usar dependencies con versiones exactas solo para utilidades seguras de duplicar.

  • Apps/servicios finales → Usar dependencies con versiones exactas para paquetes en tiempo de ejecución (React, ethers, etc.).

1. Justificación

Muchas bibliotecas dependen de singletons globales, React Context, identidad de clase, cachés compartidos, enums de esquemas o pools de BD compartidos. Instalar múltiples versiones de la misma biblioteca puede provocar:

  • Contexto no compartido entre copias

  • Cachés o pools duplicados

  • Comprobaciones instanceof que fallan

  • Desajustes de enums/símbolos

  • Aumento del tamaño del bundle

  • Errores en tiempo de ejecución difíciles de diagnosticar

La gestión correcta de dependencias previene estos problemas.

No-objetivos

Este estándar no intenta:

  • Imponer un único gestor de paquetes (npm, yarn, pnpm están todos soportados)

  • Garantizar una sola copia física en node_modules (el foco está en la deduplicación en tiempo de ejecución/bundle)

2. Definiciones

Campo
Propósito
Responsabilidad del consumidor
Aplica a

dependencies

Paquetes usados internamente por el módulo

Ninguna - no se espera que el consumidor los proporcione

Apps y bibliotecas

peerDependencies

Paquetes que deben resolverse a una sola versión efectiva en tiempo de ejecución

Debe instalarlos (o usar peerDependenciesMeta para opcionales)

Solo bibliotecas

peerDependenciesMeta

Metadatos para peerDependencies, usado para marcar peers como opcionales

Ninguna - solo afecta el comportamiento del gestor de paquetes

Solo bibliotecas

devDependencies

Herramientas usadas únicamente durante el desarrollo

Ninguna

Apps y bibliotecas

Acerca de peerDependenciesMeta

peerDependenciesMeta es un campo que proporciona metadatos sobre tus peerDependencies. El caso de uso más común es marcar peers como opcionales:

  • Peers requeridos (por defecto): El gestor de paquetes advertirá si no están instalados

  • Peers opcionales: El gestor de paquetes no advertirá si faltan; tu paquete debería manejar su ausencia con gracia

Esto es útil para paquetes que pueden funcionar con o sin ciertas dependencias (por ejemplo, una utilidad que funciona con o sin React, o una biblioteca que soporta múltiples proveedores Web3).

Apps vs Bibliotecas

Bibliotecas / Paquetes Compartidos:

  • Usar peerDependencies para paquetes que deben resolverse a una sola versión efectiva en tiempo de ejecución (React, ethers, @dcl/schemas)

  • El consumidor (app) proporciona estas dependencias

  • Previene instalaciones duplicadas y conflictos de singletons

Apps / Servicios Finales:

  • A menudo usan dependencies para paquetes en tiempo de ejecución (React, ethers, etc.)

  • Son el consumidor final, por lo que la duplicación no es una preocupación

  • peerDependencies sigue siendo válido si la app podría ser consumida como dependencia

3. Cuándo usar cada campo

Referencia rápida: Ver Sección 4 para paquetes comunes y su colocación recomendada.

Usar peerDependencies para (Solo bibliotecas):

En bibliotecas/paquetes compartidos, usar peerDependencies para paquetes que deben resolverse a una sola versión efectiva en tiempo de ejecución:

  • React, Redux, wagmi, ethers, viem

  • @dcl/schemas y bibliotecas similares de cruce de ecosistemas

  • decentraland/connect

  • Drivers de BD cuando se comparten pools

  • Cualquier biblioteca que dependa de singletons o context

✅ Correcto (Biblioteca):

❌ Incorrecto (Biblioteca usando dependencies para libs compartidas):

Usar dependencies para:

  • Utilidades seguras de duplicar (lodash-es, date-fns)

  • En apps: Paquetes en tiempo de ejecución como React, ethers (cuando la app es el consumidor final)

Importante: Siempre usar versiones exactas/fijas en dependencies para seguridad.

✅ Correcto (Biblioteca):

✅ Correcto (App):

peerDependencies opcionales (peerDependenciesMeta)

Para paquetes reusables que funcionan con o sin ciertas dependencias, usar peerDependenciesMeta para marcar peers como opcionales:

✅ Correcto:

Lo que esto significa:

  • react es requerido: El consumidor debe instalarlo o el gestor de paquetes advertirá

  • ethers es opcionales: El consumidor no necesita instalarlo; tu paquete debería comprobar su presencia antes de usarlo

Casos de uso:

  • Paquetes que funcionan tanto en entornos con React como sin React

  • Bibliotecas que soportan múltiples proveedores Web3 (ethers, viem, etc.)

  • Utilidades que mejoran otras bibliotecas pero no son obligatorias

Usar devDependencies para:

  • Herramientas (TypeScript, ESLint, testers, bundlers)

Importante: Siempre usar versiones exactas/fijas en devDependencies para asegurar un entorno de desarrollo consistente en el equipo.

✅ Correcto:

4. Ejemplos

Paquetes que DEBEN ser peerDependencies (contexto compartido / singletons)

  • react, react-dom, react-redux, react-router-dom

  • redux, @reduxjs/toolkit

  • ethers, viem, wagmi

  • @dcl/schemas, @dcl/ui-env, @dcl/crypto

  • decentraland-dapps, decentraland-ui, decentraland-ui2, decentraland-connect

  • pg, pg-pool

Paquetes que DEBERÍAN ser dependencies (seguros de duplicar)

  • lodash-es, date-fns

  • uuid, nanoid

  • zod, ajv

  • ms, mitt, fp-future

5. Estándares relacionados

Última actualización