In this article
Los 10 comandos avanzados de npm que todo desarrollador de JavaScript debería conocer
Los comandos avanzados pueden simplificar tareas complejas y ofrecer información más detallada sobre las dependencias y configuraciones de tu proyecto. Desde identificar vulnerabilidades hasta generar una lista de materiales de software (SBOM), estos comandos te ayudarán a trabajar con más eficiencia y a tener más presente la seguridad.
El administrador de paquetes npm es una herramienta indispensable en el ecosistema de JavaScript y Node.js. Es la base para gestionar dependencias, scripts y configuraciones que agilizan los flujos de trabajo de desarrollo. Tanto si creas un proyecto pequeño como una aplicación a gran escala, dominar los comandos de npm puede mejorar significativamente tu productividad y la calidad del código.
Snyk para proteger proyectos de JavaScript
La seguridad es un aspecto fundamental del desarrollo de software moderno. Snyk se integra sin problemas en tu flujo de trabajo de desarrollo en JavaScript para analizar vulnerabilidades en el código fuente, los paquetes de código abierto, las imágenes de contenedores y las configuraciones en la nube.
Mientras revisas estos comandos npm power-user, considera reforzar tu postura de seguridad al crear una cuenta gratuita de Snyk.
1. Pasar opciones de la línea de comandos a un script de npm run con --
En proyectos complejos, a menudo necesitas pasar opciones adicionales de la línea de comandos a los scripts que se ejecutan mediante npm run. Esto resulta especialmente útil cuando quieres cambiar el comportamiento de un script sin modificarlo. Por ejemplo, podrías cambiar el entorno dinámicamente, habilitar la depuración o pasar opciones de configuración.
Ejemplo de uso en un script de npm run
Para pasar opciones de la línea de comandos al programa que ejecuta un script de npm run, usa la sintaxis de doble guion --. Todo lo que aparezca después de -- se pasa directamente al script.
Aquí tienes un ejemplo sencillo:
{
"scripts": {
"start": "node app.js"
}
}
Puedes ejecutar el script start y pasar opciones adicionales al programa app.js de la siguiente manera:
npm run start -- --port=3000 --env=productionEn este caso, --port=3000 y --env=production se pasan al script app.js como argumentos posicionales.
Consideraciones de seguridad
Pasar opciones dinámicamente puede ser muy útil, pero también implica posibles riesgos de seguridad. Asegúrate de que los scripts y las opciones que pases sean seguros y no expongan información confidencial ni permitan comportamientos no deseados. Valida y depura siempre las entradas cuando trabajes con opciones dinámicas.
2. Inspeccionar árboles de dependencias con npm ls
Como desarrollador de JavaScript, necesitas entender el árbol de dependencias de tu proyecto para identificar qué vulnerabilidades afectan a los paquetes. El comando npm ls es uno de esos comandos avanzados que te ayudan a inspeccionar el árbol de dependencias de tu proyecto. Muestra una vista de árbol ASCII de todos los paquetes de los que depende tu proyecto, incluidas sus versiones y relaciones jerárquicas.
Sintaxis y opciones de filtrado del comando npm ls
La sintaxis básica del comando npm ls es:
npm ls [<package-name>]Este comando puede mostrar todas las dependencias o centrarse en un paquete específico si indicas su nombre. Además, puedes filtrar los resultados para mostrar solo las dependencias de producción o de desarrollo usando las opciones --production o --development, respectivamente.
Ejemplo: encontrar dependencias afectadas por una vulnerabilidad específica
Supongamos que descubriste una vulnerabilidad de denegación de servicio en el paquete de npm ms npm. Para identificar qué dependencias de tu proyecto se ven afectadas por esta versión vulnerable, puedes usar el comando npm ls:
Este comando mostrará el árbol de dependencias y destacará dónde se usa ms. Este es un ejemplo de los resultados:
> npm ls ms
goof@1.0.1 /Users/lirantal/projects/repos/nodejs-goof
├─┬ express-session@1.17.2
│ └─┬ debug@2.6.9
│ └── ms@2.0.0
├─┬ express@4.12.4
│ ├─┬ debug@2.2.0
│ │ └── ms@0.7.1
│ ├─┬ finalhandler@0.3.6
│ │ └─┬ debug@2.2.0
│ │ └── ms@0.7.1
│ └─┬ send@0.12.3
│ ├─┬ debug@2.2.0
│ │ └── ms@0.7.1 deduped
│ └── ms@0.7.1
├─┬ humanize-ms@1.0.1
│ └── ms@0.6.2
├─┬ method-override@3.0.0
│ └─┬ debug@3.1.0
│ └── ms@2.0.0
├─┬ mongoose@4.2.4
│ ├─┬ mquery@1.6.3
│ │ └─┬ debug@2.2.0
│ │ └── ms@0.7.1
│ └── ms@0.7.1
├─┬ morgan@1.10.0
│ └─┬ debug@2.6.9
│ └── ms@2.0.0También puedes buscar una versión específica: ms@0.7.1.
3. Comprender las dependencias transitivas con npm why
En proyectos grandes de JavaScript, gestionar dependencias puede volverse complejo, sobre todo cuando se trata de dependencias transitivas: aquellas que no se incluyen directamente en tu package.json, pero que requieren tus dependencias directas.
Identificar por qué se incluye un paquete específico en tu proyecto puede ser fundamental para depurar y proteger tu aplicación. El comando npm why responde a esta necesidad: ofrece información detallada sobre por qué se instala un paquete determinado.
El comando npm why es fácil de usar. La sintaxis básica es:
> npm why ms@0.7.1
ms@0.7.1
node_modules/send/node_modules/ms
ms@"0.7.1" from send@0.12.3
node_modules/send
send@"0.12.3" from express@4.12.4
node_modules/express
express@"4.12.4" from the root project
send@"0.12.3" from serve-static@1.9.3
node_modules/serve-static
serve-static@"~1.9.3" from express@4.12.4
node_modules/express
express@"4.12.4" from the root project
ms@"0.7.1" from debug@2.2.0
node_modules/send/node_modules/debug
debug@"~2.2.0" from send@0.12.3
node_modules/send
send@"0.12.3" from express@4.12.4
node_modules/express
express@"4.12.4" from the root project
send@"0.12.3" from serve-static@1.9.3
node_modules/serve-static
serve-static@"~1.9.3" from express@4.12.4
node_modules/express
express@"4.12.4" from the root projectComo puedes ver, este comando de npm mostrará una explicación detallada de por qué se incluye ms, y la cadena de dependencias que llevó a su instalación.
Consejos adicionales para el comando npm why
Especifica la versión: Si sabes qué versión específica causa problemas, inclúyela en el comando para obtener resultados más precisos:
npm why ms@0.7.1Usa los resultados en JSON: Para obtener resultados más completos y detallados que incluyan los tipos de dependencias y otros metadatos, usa la opción
--json:
npm why ms@0.7.1 --jsonEsto puede ser particularmente útil para scripts automatizados o análisis más detallados.
Comprender las dependencias transitivas es fundamental para mantener una base de código segura y eficiente. Herramientas como Snyk Open Source pueden ayudarte a analizar tus dependencias en busca de vulnerabilidades conocidas y ofrecerte información útil. Regístrate aquí para obtener una cuenta gratuita de Snyk y proteger tus proyectos hoy mismo.
Si estás empezando con la gestión de dependencias y quieres entender cómo funcionan los archivos de bloqueo, otro recurso útil es el artículo “¿Qué es package-lock.json y cómo funciona un archivo de bloqueo para los paquetes de yarn y npm?”. Este artículo explica el control de versiones semántico, los archivos de bloqueo shrinkwrap, los archivos de bloqueo que se desactualizan y otros conceptos importantes sobre los archivos de bloqueo de npm.
4. Mostrar los scripts del ciclo de vida disponibles con npm run
Cuando trabajas en un proyecto de JavaScript o Node.js, a menudo necesitas ejecutar varios scripts definidos en el archivo package.json, ¿verdad? Algunos ejemplos son npm run test y npm run build.
Sin embargo, recordar los nombres exactos de todos estos scripts del npm lifecycle puede ser difícil, sobre todo en proyectos grandes o si trabajas con varios proyectos con regularidad (backend y frontend).
¡El comando npm run viene al rescate! Resuelve este problema al mostrar todos los scripts del ciclo de vida disponibles en tu proyecto, para que puedas ver fácilmente cuáles hay y cómo ejecutarlos.
Aquí tienes un ejemplo práctico de cómo ver todos los scripts de npm run de un proyecto:
> npm run
Lifecycle scripts included in goof@1.0.1:
start
NODE_OPTIONS=--openssl-legacy-provider node app.js
test
snyk test
available via `npm run-script`:
dev
NODE_OPTIONS=--openssl-legacy-provider nodemon ./app.js
build
browserify -r jquery > public/js/bundle.js
cleanup
mongo express-todo --eval 'db.todos.remove({});'Los resultados muestran todos los scripts de npm run disponibles en el proyecto, junto con los comandos que ejecutan. ¡Así te ahorras unos segundos que de otro modo pasarías abriendo el archivo package.json en tu IDE o terminal!
5. Búsquedas avanzadas de dependencias con npm query
Supongo que esta función del administrador de paquetes npm no es muy conocida. Te permite filtrar y seleccionar dependencias según sus atributos. Quizá necesites hacerlo para comprender el impacto de una dependencia de terceros o realizar acciones específicas, pero encontrar la dependencia de npm adecuada puede ser complicado.
El comando npm query, incorporado en npm@8, ofrece una forma eficaz de realizar búsquedas avanzadas de dependencias mediante un lenguaje de consulta. Permite filtrar y seleccionar dependencias según sus atributos, lo que facilita la gestión y auditoría de las dependencias de tu proyecto.
Cómo usar la sintaxis de npm query
La sintaxis del comando npm query es:
npm query "<query>"La parte de la consulta es lo complicado. Se trata de su propio lenguaje (DSL), que admite varios atributos y operadores para afinar la búsqueda. Por ejemplo, puedes filtrar dependencias según sus scripts del ciclo de vida, versiones u otros metadatos de los paquetes de terceros.
Ejemplo: encontrar dependencias con un script postinstall de npm
Supongamos que quieres encontrar todas las dependencias de tu proyecto que tienen un script postinstall. Esto puede ser útil para identificar paquetes que ejecutan scripts durante la instalación, lo que podría presentar riesgos de seguridad o afectar el proceso de compilación. Puedes usar la siguiente consulta:
npm query ":attr(scripts, [postinstall])"Este comando devolverá una lista de dependencias que tienen definido un script postinstall en su archivo package.json .
Los resultados podrían verse así:
[
{
"name": "some-package",
"version": "1.0.0",
"scripts": {
"postinstall": "node setup.js"
}
}
]En este ejemplo, some-package tiene un script postinstall que ejecuta node setup.js. Esta información puede ayudarte a auditar tus dependencias para detectar posibles riesgos de seguridad o comportamientos no deseados.
Consejo adicional: usa npq tool, la herramienta de seguridad de código abierto para la cadena de suministro, como medida preventiva para detectar si las dependencias que vas a instalar tienen scripts postinstall o preinstall antes de instalarlas.
6. Comparar versiones con npm diff
Comprender los cambios entre distintas versiones de un paquete es fundamental para mantener una base de código segura y estable. Esto resulta útil si quieres identificar qué cambió entre dos versiones de un paquete.
El comando npm diff te ayuda a comparar dos versiones de un paquete. Es especialmente útil para identificar posibles problemas de seguridad, funciones obsoletas, dependencias modificadas o cambios importantes que podrían afectar tu aplicación.
El comando npm diff es fácil de usar y se parece al comando git diff:
npm diff --diff=<package@version1> --diff=<package@version2>Supongamos que quieres comparar los cambios entre las versiones 2.1.2 y 2.1.3 del paquete ms. Ejecutarías el siguiente comando:
npm diff --diff=ms@2.1.3 --diff=ms@2.1.2Los resultados mostrarán las diferencias en el código, de forma similar a los resultados de git diff:
diff --git a/index.js b/index.js
index v2.1.3..v2.1.2 100644
--- a/index.js
+++ b/index.js
@@ -23,7 +23,7 @@
* @api public
*/
-module.exports = function (val, options) {
+module.exports = function(val, options) {
options = options || {};
var type = typeof val;
if (type === 'string' && val.length > 0) {
diff --git a/package.json b/package.json
index v2.1.3..v2.1.2 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "ms",
- "version": "2.1.3",
+ "version": "2.1.2",
"description": "Tiny millisecond conversion utility",
- "repository": "vercel/ms",
+ "repository": "zeit/ms",
"main": "./index",
"files": [
"index.js"
@@ -28,11 +28,10 @@
},
"license": "MIT",
"devDependencies": {
- "eslint": "4.18.2",
+ "eslint": "4.12.1",
"expect.js": "0.3.1",
"husky": "0.14.3",
"lint-staged": "5.0.0",
- "mocha": "4.0.1",
- "prettier": "2.0.5"
+ "mocha": "4.0.1"
}
}
diff --git a/license.md b/license.md
index v2.1.3..v2.1.2 100644
--- a/license.md
+++ b/license.md
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2020 Vercel, Inc.
+Copyright (c) 2016 Zeit, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/readme.md b/readme.md
index v2.1.3..v2.1.2 100644
--- a/readme.md
+++ b/readme.md
@@ -1,6 +1,7 @@
# ms
-
+[](https://travis-ci.org/zeit/ms)
+[](https://spectrum.chat/zeit)
Use this package to easily convert various time formats to milliseconds.Ahora puedes revisar los cambios para asegurarte de que no introduzcan vulnerabilidades de seguridad ni cambios incompatibles.
7. Crear y analizar SBOM con npm sbom
SBOM significa Software Bill of Materials (lista de materiales de software) y es una lista detallada de todos los componentes y dependencias de tu software, como una receta que enumera todos los ingredientes.
Esta transparencia ayuda a identificar posibles vulnerabilidades y garantiza el cumplimiento de varios estándares de seguridad. Las SBOM son particularmente importantes para la seguridad de la cadena de suministro, donde conocer los componentes de tu software es fundamental para gestionar riesgos y generar confianza.
Los equipos de seguridad suelen usar las SBOM para garantizar el cumplimiento de estándares y regulaciones del sector, como la Orden Ejecutiva sobre Ciberseguridad.
Cómo usar npm sbom e integrarlo con Snyk
El comando npm sbom genera una SBOM para tu proyecto o espacio de trabajo.
Es especialmente útil cuando se combina con Snyk, una herramienta de seguridad para desarrolladores que analiza vulnerabilidades en el código fuente, los paquetes de código abierto, las imágenes de contenedores y las configuraciones en la nube.
Puedes usar npm como administrador de paquetes para generar una SBOM de todas las dependencias del proyecto y después enviar a Snyk el árbol de dependencias completo para analizarlo en busca de vulnerabilidades. Y puedes hacer todo esto directamente desde la CLI.
Esta es la sintaxis básica para crear una SBOM en formato CycloneDX con npm sbom:
npm sbom --sbom-format cyclonedx > sbom.cdx.jsonAhora puedes analizar esta SBOM en busca de vulnerabilidades con Snyk:
snyk sbom test --experimental --file=sbom.cdx.jsonEsto generará una lista de las vulnerabilidades encontradas en la SBOM, con sus niveles de gravedad:
× [HIGH] Regular Expression Denial of Service (ReDoS)
Introduced through: pkg:npm/negotiator@0.2.8
URL: https://security.snyk.io/vuln/npm:negotiator:20160616
× [HIGH] Uninitialized Memory Exposure
Introduced through: pkg:npm/npmconf@0.0.24
URL: https://security.snyk.io/vuln/npm:npmconf:20180512
× [HIGH] Prototype Override Protection Bypass
Introduced through: pkg:npm/qs@2.2.4
URL: https://security.snyk.io/vuln/npm:qs:20170213
× [CRITICAL] Incomplete List of Disallowed Inputs
Introduced through: pkg:npm/babel-traverse@6.26.0
URL: https://security.snyk.io/vuln/SNYK-JS-BABELTRAVERSE-5962463
× [CRITICAL] Prototype Pollution
Introduced through: pkg:npm/handlebars@4.0.11
URL: https://security.snyk.io/vuln/SNYK-JS-HANDLEBARS-534988
× [CRITICAL] Server-side Request Forgery (SSRF)
Introduced through: pkg:npm/parse-url@5.0.1
URL: https://security.snyk.io/vuln/SNYK-JS-PARSEURL-2936249
× [CRITICAL] Arbitrary File Write via Archive Extraction (Zip Slip)
Introduced through: pkg:npm/adm-zip@0.4.7
URL: https://security.snyk.io/vuln/npm:adm-zip:20180415
╭──────────────────────────────────────────────────────────────────────╮
│ Test summary │
│ Organization: a30b7399-4e0c-4f6e-ba84-b27e131db54c │
│ Test type: Software Bill of Materials │
│ Path: sbom.cdx.json │
│ │
│ Open issues: 148 [ 4 CRITICAL 64 HIGH 72 MEDIUM 8 LOW ] │
╰──────────────────────────────────────────────────────────────────────╯8. Fijar dependencias con overrides en package.json
Como quizá ya hayas experimentado, la gestión de dependencias puede ser un arma de doble filo. Aunque npm facilita muchísimo incluir y gestionar dependencias, también puede hacer que tu proyecto sea vulnerable a problemas de seguridad que surjan de dependencias transitivas.
Un problema importante al que se enfrentan los desarrolladores es la aparición de vulnerabilidades o cambios incompatibles en estas dependencias transitivas. Por ejemplo, un paquete de uso extendido podría introducir de repente una vulnerabilidad o un cambio incompatible que afecte a todo tu proyecto.
npm ofrece una función eficaz llamada overrides en el archivo package.json para mitigar estos riesgos. Esta función te permite fijar versiones específicas de dependencias directas y transitivas, y garantizar que tu proyecto use solo las versiones en las que confías.
Un caso real en el que los overrides fueron invaluables ocurrió durante el incidente de seguridad de protestware de los paquetes peacenotwar y node-ipc en marzo de 2022, cuando ayudaron a mitigar las interrupciones para quienes usaban esos paquetes.
Cómo usar la configuración overrides en package.json
Para usar la función overrides, agrega una sección overrides a tu archivo package.json. Esta sección especifica qué versiones de las dependencias se deben usar, independientemente de lo que indiquen los archivos package.json propios de esas dependencias.
Aquí tienes un ejemplo básico de cómo usar overrides:
{
"name": "your-project",
"version": "1.0.0",
"dependencies": {
"some-package": "^2.0.0"
},
"overrides": {
"node-ipc@>9.2.1 <10": "9.2.1",
"node-ipc@>10.1.0": "10.1.0"
}
}En este ejemplo:
El paquete
node-ipcse fija en la versión 9.2.1 para las versiones posteriores a la 9.2.1 e inferiores a la 10.El paquete
node-ipcse fija en la versión 10.1.0 para las versiones posteriores a la 10.1.0.
Mejora la seguridad con Snyk
Aunque fijar las dependencias puede ayudar a mitigar algunos riesgos, no es una solución infalible. Es fundamental analizar tu proyecto periódicamente para detectar vulnerabilidades. Una herramienta de seguridad pensada para desarrolladores, como Snyk, detecta lo antes posible casos de malware, protestware y vulnerabilidades de seguridad en general en tus dependencias, y te ayuda a corregirlos.
Para comenzar a usar Snyk, regístrate aquí para obtener una cuenta gratuita.
9. Desarrollo de paquetes locales con npm install
Al desarrollar paquetes de npm de forma local, a menudo necesitas probarlos dentro de otro proyecto. Si no conoces esta función integrada de npm, tendrías que publicar el paquete en el registro de npm, lo que puede ser engorroso y llevar mucho tiempo, sobre todo si necesitas hacer cambios frecuentes.
El comando npm install <path-to-package-in-disk-directory> resuelve este problema, ya que te permite instalar y vincular paquetes locales directamente desde tu directorio de desarrollo. Esto crea un enlace simbólico al directorio del disco donde desarrollas el paquete, lo que permite actualizarlo y probarlo fácilmente sin tener que publicarlo repetidamente (tampoco necesitas desinstalarlo y volver a instalarlo localmente gracias al enlace simbólico).
Para usar este comando, ve al directorio raíz del proyecto en el que quieres instalar el paquete local. Luego, ejecuta el siguiente comando:
npm install /path/to/local/packageReemplaza /path/to/local/package por la ruta real al directorio de tu paquete local. Este comando crea un enlace simbólico entre el directorio node_module's de tu proyecto y el directorio del paquete local.
Ventajas prácticas de instalar paquetes localmente con npm
Actualizaciones inmediatas: Los cambios en el paquete local se reflejan de inmediato en el proyecto, sin necesidad de volver a publicarlo.
Depuración simplificada: Puedes depurar y probar tu paquete en tiempo real dentro del contexto del proyecto más amplio.
Flujo de trabajo eficiente: Agiliza el proceso de desarrollo al reducir la carga asociada con el control de versiones y la publicación de paquetes.
10. Seguridad y compatibilidad con una configuración .npmrc
El archivo .npmrc es un archivo de configuración de npm que te permite personalizar el comportamiento de los comandos de npm. Cumple una función clave para mejorar la seguridad y la compatibilidad de tus proyectos de Node.js. Al configurar ciertos ajustes en el archivo .npmrc, puedes proteger tus proyectos de paquetes maliciosos y asegurarte de que tus dependencias sean compatibles con versiones específicas del entorno de ejecución de Node.js.
Ignora los scripts para reforzar la seguridad
Una de las formas más efectivas de proteger tu proyecto de paquetes dañinos y maliciosos es desactivar la ejecución de scripts del ciclo de vida. Estos scripts pueden ejecutar comandos arbitrarios durante la instalación, lo que representa un riesgo de seguridad.
Al establecer ignore-scripts=true en tu archivo .npmrc, puedes impedir que se ejecuten estos scripts:
# .npmrc
ignore-scripts=trueEsta configuración garantiza que npm no ejecute ningún script preinstall, postinstall ni otros scripts del ciclo de vida, lo que reduce el riesgo de ejecutar código malicioso.
Compatibilidad con versiones del entorno de ejecución de Node.js
Otro aspecto importante para mantener un proyecto seguro y estable es garantizar la compatibilidad con versiones específicas del entorno de ejecución de Node.js. Esto es especialmente útil si tu proyecto depende de versiones antiguas o sin soporte de Node.js. Al establecer node-version en tu archivo .npmrc, puedes indicarle a npm que solo actualice las dependencias compatibles con la versión de Node.js especificada:
# .npmrc
node-version=14.0.0Esta configuración garantiza que npm solo considere las dependencias que coincidan con el rango de versiones especificado de Node.js en la configuración del archivo de manifiesto engines.
Próximos pasos
Los comandos Power-user npm son útiles no solo para administrar dependencias, sino también para mejorar la seguridad y la eficiencia de tu flujo de trabajo de desarrollo.
También te puede interesar leer otros artículos sobre Node.js:
Las diez mejores prácticas de seguridad para npm que protegen tus proyectos de JavaScript.
Diez funciones modernas del entorno de ejecución de Node.js que puedes empezar a usar en 2024
Diez mejores prácticas para contenerizar aplicaciones web de Node.js con Docker
Mejores prácticas para crear un paquete npm moderno con la seguridad en mente, de Brian Clark.
Herramienta gratuita para revisar código
Protege tu código antes de tu próximo commit.