JavaScript
Tutorial JavaScript: NPM y dependencias
NPM, el estándar para JavaScript. Aprende sus conceptos básicos, inicializa proyectos y compara con Yarn en esta lección.
Aprende JavaScript y certifícateIntroducción a NPM: Conceptos básicos
NPM (Node Package Manager) es el gestor de paquetes estándar para JavaScript, que viene integrado con Node.js. Funciona como un ecosistema que permite a los desarrolladores compartir, descubrir y utilizar código de otros desarrolladores, así como gestionar las dependencias de sus proyectos de manera eficiente.
¿Qué es NPM?
NPM cumple tres funciones principales en el desarrollo con JavaScript:
- Es un repositorio en línea donde se almacenan paquetes de código abierto
- Es una herramienta de línea de comandos que permite interactuar con dicho repositorio
- Es un estándar para la gestión de dependencias en proyectos JavaScript
El repositorio de NPM contiene más de 1.3 millones de paquetes, lo que lo convierte en el mayor registro de software del mundo. Esta enorme biblioteca de código reutilizable permite a los desarrolladores construir aplicaciones complejas sin tener que "reinventar la rueda".
Estructura básica
Cuando trabajamos con NPM, nuestro proyecto suele tener la siguiente estructura básica:
mi-proyecto/
├── node_modules/ # Directorio donde se instalan las dependencias
├── package.json # Archivo de configuración del proyecto
├── package-lock.json # Bloqueo exacto de versiones de dependencias
└── src/ # Código fuente de nuestra aplicación
El directorio node_modules
es donde NPM instala todos los paquetes que nuestro proyecto necesita. Este directorio no debe incluirse en el control de versiones, ya que puede ser muy grande y se puede reconstruir a partir del archivo package.json.
Inicialización de un proyecto
Para comenzar a utilizar NPM en un proyecto, primero debemos inicializarlo. Esto se hace con el comando:
npm init
Este comando inicia un asistente interactivo que nos guía a través de la creación del archivo package.json. Para aceptar todas las opciones por defecto, podemos usar:
npm init -y
Semántica de versiones
NPM utiliza el versionado semántico (SemVer) para gestionar las versiones de los paquetes. Este sistema utiliza tres números separados por puntos:
- 1. - Versión mayor (cambios incompatibles con versiones anteriores)
- 1.2 - Versión menor (nuevas funcionalidades compatibles)
- 1.2.3 - Parche (correcciones de errores compatibles)
En el package.json, podemos especificar qué actualizaciones queremos permitir usando estos símbolos:
- ^1.2.3: Acepta actualizaciones de versiones menores y parches (1.x.x)
- ~1.2.3: Acepta solo actualizaciones de parches (1.2.x)
- 1.2.3: Versión exacta, sin actualizaciones
Registros de NPM
El registro público de NPM es donde se almacenan la mayoría de los paquetes, pero también es posible configurar y utilizar registros privados para código propietario o interno de una organización.
Para publicar o instalar paquetes desde un registro específico, podemos usar el parámetro --registry
:
npm install lodash --registry=https://registry.ejemplo.com
También podemos configurar un registro por defecto para nuestro proyecto o de forma global.
NPM vs Yarn vs pnpm
Aunque NPM es el gestor de paquetes por defecto, existen alternativas populares:
- Yarn: Desarrollado por Facebook, ofrece mejor rendimiento y algunas características adicionales
- pnpm: Utiliza un almacenamiento eficiente de paquetes mediante enlaces simbólicos
La elección entre estos gestores depende de las necesidades específicas del proyecto, pero todos utilizan el mismo ecosistema de paquetes y son compatibles con el formato package.json.
Seguridad en NPM
La seguridad es un aspecto fundamental al trabajar con dependencias externas. NPM incluye herramientas para analizar vulnerabilidades:
npm audit
Este comando revisa las dependencias de nuestro proyecto y nos informa de posibles problemas de seguridad. Para corregir automáticamente las vulnerabilidades (cuando sea posible):
npm audit fix
Configuración global de NPM
NPM almacena su configuración en el archivo .npmrc
, que puede existir a nivel global o por proyecto. Algunas configuraciones útiles son:
save-exact=true # Guarda versiones exactas en package.json
fund=false # Desactiva mensajes de financiación
loglevel=warn # Establece el nivel de detalle de los logs
Para ver la configuración actual:
npm config list
NPM es una herramienta esencial en el desarrollo moderno con JavaScript, que facilita enormemente la gestión de dependencias y la reutilización de código. Dominar sus conceptos básicos es el primer paso para construir aplicaciones JavaScript robustas y mantenibles.
Package.json explicado: Configuración esencial
El archivo package.json
es el corazón de cualquier proyecto JavaScript moderno. Este archivo de configuración en formato JSON define las características del proyecto, sus dependencias y los scripts disponibles para automatizar tareas. Entender a fondo este archivo es fundamental para gestionar proyectos JavaScript de manera eficiente.
Estructura básica del package.json
Un archivo package.json
típico contiene varios campos clave que definen diferentes aspectos del proyecto:
{
"name": "mi-aplicacion",
"version": "1.0.0",
"description": "Una aplicación JavaScript moderna",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"test": "jest"
},
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"jest": "^29.5.0"
}
}
Metadatos del proyecto
Los campos de metadatos proporcionan información descriptiva sobre el proyecto:
- name: Identificador único del proyecto (obligatorio para publicar)
- version: Versión actual siguiendo el formato SemVer (obligatorio para publicar)
- description: Breve descripción del propósito del proyecto
- author: Información sobre el creador del proyecto
- license: Licencia bajo la cual se distribuye el código
- keywords: Etiquetas para mejorar la búsqueda si el paquete es público
- homepage: URL del sitio web del proyecto
- repository: Información sobre el repositorio de código fuente
{
"name": "mi-libreria",
"version": "1.2.3",
"description": "Librería de utilidades para procesamiento de datos",
"author": "Ana García <ana@ejemplo.com>",
"license": "MIT",
"keywords": ["utilidades", "procesamiento", "datos"],
"repository": {
"type": "git",
"url": "https://github.com/anagarcia/mi-libreria.git"
}
}
Puntos de entrada
El campo main
define el punto de entrada principal del paquete cuando es importado por otro proyecto:
{
"main": "dist/index.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
}
- main: Punto de entrada para CommonJS (Node.js)
- module: Punto de entrada para módulos ES (navegadores modernos)
- types: Definiciones de TypeScript para editores e IDEs
Gestión de dependencias
Las dependencias se dividen en varias categorías según su propósito:
- dependencies: Paquetes necesarios para que la aplicación funcione en producción
- devDependencies: Paquetes necesarios solo durante el desarrollo
- peerDependencies: Paquetes que se espera que el consumidor del paquete proporcione
- optionalDependencies: Paquetes opcionales que no bloquean la instalación si fallan
{
"dependencies": {
"axios": "^0.27.2",
"lodash": "~4.17.21"
},
"devDependencies": {
"eslint": "^8.36.0",
"webpack": "^5.76.3"
},
"peerDependencies": {
"react": ">=17.0.0"
}
}
Especificadores de versión
Los especificadores de versión permiten controlar qué actualizaciones se aceptan:
- ^1.2.3: Permite actualizaciones que no cambien el primer dígito no cero (^0.2.3 solo permite 0.2.x)
- ~1.2.3: Permite solo actualizaciones de parche (1.2.x)
- 1.2.3: Versión exacta
- >1.2.3: Mayor que la versión especificada
- >=1.2.3: Mayor o igual que la versión especificada
- <1.2.3: Menor que la versión especificada
- 1.2.x: Cualquier versión que coincida con el patrón
- *: Cualquier versión
- latest: La última versión disponible
Scripts de NPM
El campo scripts
define comandos personalizados que pueden ejecutarse con npm run
:
{
"scripts": {
"start": "node server.js",
"build": "webpack --mode production",
"test": "jest",
"lint": "eslint src/**/*.js",
"dev": "webpack serve --mode development"
}
}
Estos scripts pueden encadenarse y combinarse:
{
"scripts": {
"prebuild": "npm run clean",
"build": "webpack",
"postbuild": "npm run test",
"clean": "rimraf dist"
}
}
Los prefijos pre
y post
definen scripts que se ejecutan automáticamente antes y después del script principal.
Configuración de entorno
El campo engines
especifica las versiones compatibles de Node.js y npm:
{
"engines": {
"node": ">=14.0.0",
"npm": ">=7.0.0"
}
}
Esto ayuda a garantizar que el proyecto se ejecute en un entorno adecuado.
Configuración de publicación
Para controlar qué archivos se incluyen al publicar el paquete:
{
"files": [
"dist",
"README.md"
],
"private": false,
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
}
}
- files: Lista de archivos/directorios a incluir (alternativa a .npmignore)
- private: Evita la publicación accidental si es
true
- publishConfig: Configuración específica para la publicación
Configuración de Workspaces
Para proyectos monorepo, los workspaces permiten gestionar múltiples paquetes en un solo repositorio:
{
"workspaces": [
"packages/*"
]
}
Esto permite instalar dependencias para todos los paquetes con un solo comando y gestionar referencias entre ellos.
Configuración personalizada
El package.json también puede contener configuración específica para herramientas:
{
"eslintConfig": {
"extends": "eslint:recommended"
},
"jest": {
"testEnvironment": "node"
},
"browserslist": [
">0.2%",
"not dead"
]
}
Estas secciones son utilizadas por las herramientas correspondientes para configurar su comportamiento sin necesidad de archivos adicionales.
Resolución de dependencias
El campo resolutions
(en Yarn) o overrides
(en npm) permite forzar versiones específicas de dependencias transitivas:
{
"overrides": {
"lodash": "4.17.21"
}
}
Esto es útil para solucionar problemas de seguridad o incompatibilidades en dependencias indirectas.
El archivo package.json es una herramienta flexible que va más allá de simplemente listar dependencias. Dominar su configuración te permitirá optimizar el flujo de trabajo de desarrollo y garantizar la consistencia en tus proyectos JavaScript.
Instalación de paquetes: Comandos principales
La instalación y gestión de paquetes es una de las tareas fundamentales cuando trabajamos con NPM. Conocer los comandos principales nos permite incorporar bibliotecas externas, actualizar dependencias y mantener nuestro proyecto en óptimas condiciones. Veamos los comandos más importantes y cómo utilizarlos eficientemente.
Instalación básica de paquetes
El comando más utilizado en NPM es npm install
(o su forma abreviada npm i
), que nos permite añadir dependencias a nuestro proyecto:
npm install lodash
Este comando realiza varias acciones:
- Descarga el paquete desde el registro de NPM
- Lo guarda en el directorio
node_modules
- Actualiza el archivo
package.json
añadiendo la dependencia - Actualiza el archivo
package-lock.json
con la versión exacta
Por defecto, los paquetes se añaden a la sección dependencies
del package.json. Para instalar dependencias de desarrollo, utilizamos la bandera --save-dev
o -D
:
npm install jest --save-dev
Tipos de instalación
NPM ofrece diferentes modos de instalación según nuestras necesidades:
- Instalación local (por defecto): Instala el paquete en el proyecto actual
- Instalación global: Instala el paquete a nivel de sistema
# Instalación global (requiere permisos de administrador en algunos sistemas)
npm install -g typescript
# Verificar paquetes instalados globalmente
npm list -g --depth=0
Los paquetes globales suelen ser herramientas de línea de comandos que necesitamos usar en múltiples proyectos, como compiladores o generadores de código.
Opciones de instalación comunes
Existen varias banderas útiles que podemos usar con el comando install:
# Instalar una versión específica
npm install express@4.17.1
# Instalar la última versión (ignorando package.json)
npm install lodash@latest
# Instalar sin añadir al package.json
npm install moment --no-save
# Instalar como dependencia opcional
npm install sharp --save-optional
# Instalar como dependencia de igual nivel (peer dependency)
npm install react --save-peer
Instalación desde package.json
Cuando clonamos un repositorio o recibimos un proyecto, necesitamos instalar todas las dependencias definidas en el package.json:
# Instalar todas las dependencias
npm install
# Instalar solo dependencias de producción (sin devDependencies)
npm install --production
Este comando lee el package.json y reconstruye el directorio node_modules
con todas las dependencias necesarias.
Actualización de paquetes
Mantener las dependencias actualizadas es importante para aprovechar mejoras y correcciones de seguridad:
# Ver qué paquetes tienen actualizaciones disponibles
npm outdated
# Actualizar un paquete específico
npm update lodash
# Actualizar todos los paquetes respetando semver
npm update
Para actualizar a versiones mayores (que pueden incluir cambios incompatibles):
# Instalar la herramienta npm-check-updates
npm install -g npm-check-updates
# Verificar actualizaciones disponibles
ncu
# Actualizar todas las dependencias a la última versión
ncu -u
npm install
Eliminación de paquetes
Para eliminar dependencias que ya no necesitamos:
# Eliminar un paquete y quitarlo del package.json
npm uninstall axios
# Eliminar un paquete de desarrollo
npm uninstall jest --save-dev
# Eliminar un paquete global
npm uninstall -g typescript
Gestión del caché
NPM mantiene una caché local para mejorar el rendimiento. A veces es necesario gestionarla:
# Ver el tamaño de la caché
npm cache verify
# Limpiar la caché completamente
npm cache clean --force
Instalación desde fuentes alternativas
NPM permite instalar paquetes desde diferentes fuentes:
# Desde un repositorio Git
npm install git+https://github.com/usuario/proyecto.git
# Desde una carpeta local
npm install ../mi-paquete-local
# Desde un archivo tarball
npm install ./paquete.tgz
Instalación con banderas de seguridad
Para proyectos con requisitos de seguridad estrictos:
# Verificar vulnerabilidades antes de instalar
npm install express --audit
# Instalar ignorando scripts (más seguro)
npm install moment --ignore-scripts
Instalación en entornos CI/CD
En entornos de integración continua, es recomendable usar estas opciones:
# Instalación más rápida (solo para CI)
npm ci
# Instalación sin generar logs
npm install --silent
El comando npm ci
es especialmente útil en pipelines de CI/CD porque:
- Elimina completamente
node_modules
antes de instalar - Instala exactamente las versiones del package-lock.json
- Es más rápido en instalaciones limpias
- Falla si hay discrepancias entre package.json y package-lock.json
Resolución de problemas comunes
Cuando enfrentamos problemas de instalación, estos comandos pueden ayudar:
# Forzar una instalación limpia
rm -rf node_modules package-lock.json
npm install
# Verificar permisos y configuración
npm doctor
# Instalar con logs detallados para depuración
npm install --verbose
Dominar estos comandos de instalación te permitirá gestionar eficientemente las dependencias de tus proyectos JavaScript, manteniendo un equilibrio entre actualización, estabilidad y seguridad.
Ejercicios de esta lección NPM y dependencias
Evalúa tus conocimientos de esta lección NPM y dependencias con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Funciones flecha
Polimorfismo
Array
Transformación con map()
Gestor de tareas con JavaScript
Manipulación DOM
Funciones
Funciones flecha
Async / Await
Creación y uso de variables
Excepciones
Promises
Funciones cierre (closure)
Herencia
Herencia
Estructuras de control
Selección de elementos DOM
Modificación de elementos DOM
Filtrado con filter() y find()
Funciones cierre (closure)
Funciones
Mapas con Map
Reducción con reduce()
Callbacks
Manipulación DOM
Promises
Async / Await
Eventos del DOM
Async / Await
Promises
Filtrado con filter() y find()
Callbacks
Creación de clases y objetos Restaurante
Reducción con reduce()
Filtrado con filter() y find()
Reducción con reduce()
Conjuntos con Set
Herencia de clases
Eventos del DOM
Clases y objetos
Modificación de elementos DOM
Mapas con Map
Introducción a JavaScript
Funciones
Tipos de datos
Clases y objetos
Array
Conjuntos con Set
Array
Encapsulación
Clases y objetos
Uso de operadores
Uso de operadores
Estructuras de control
Excepciones
Transformación con map()
Funciones flecha
Selección de elementos DOM
Encapsulación
Mapas con Map
Creación y uso de variables
Polimorfismo
Tipos de datos
Estructuras de control
Todas las lecciones de JavaScript
Accede a todas las lecciones de JavaScript y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Javascript
Introducción Y Entorno
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Funciones Cierre (Closure)
Sintaxis
Arrays Y Métodos
Estructuras De Datos
Conjuntos Con Set
Estructuras De Datos
Mapas Con Map
Estructuras De Datos
Funciones Flecha
Programación Funcional
Filtrado Con Filter() Y Find()
Programación Funcional
Transformación Con Map()
Programación Funcional
Reducción Con Reduce()
Programación Funcional
Clases Y Objetos
Programación Orientada A Objetos
Excepciones
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
Manipulación Dom
Dom
Selección De Elementos Dom
Dom
Modificación De Elementos Dom
Dom
Eventos Del Dom
Dom
Callbacks
Programación Asíncrona
Promises
Programación Asíncrona
Async / Await
Programación Asíncrona
Certificados de superación de JavaScript
Supera todos los ejercicios de programación del curso de JavaScript y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el rol de NPM en el ecosistema JavaScript.
- Conocer la estructura básica de un proyecto NPM.
- Aprender a inicializar un proyecto con npm init.
- Entender el versionado semántico (SemVer).
- Gestionar dependencias con package.json y package-lock.json.
- Diferenciar entre repositorios públicos y privados en NPM.
- Comparar NPM con Yarn y pnpm.
- Implementar prácticas de seguridad mediante npm audit.
- Configurar NPM a nivel global y por proyecto.