
Curso de entrada al dominio de front-end (vue): ingresando al aprendizaje
Hoy en día, los estudiantes de desarrollo front-end no pueden prescindir de npm , una herramienta de administración de paquetes que es muy útil para toda la próspera comunidad NodeJS . comprender su mecanismo interno ayuda a profundizar nuestra comprensión del desarrollo de módulos y varias configuraciones de ingeniería front-end para acelerar nuestra resolución de problemas (creo que muchos estudiantes han tenido problemas con varios problemas de dependencia).
Este artículo realiza un análisis detallado del mecanismo de administración de paquetes de npm desde tres perspectivas: package.json , administración de versiones, instalación de dependencias y ejemplos específicos.

En Node.js , un módulo es una biblioteca o marco y también un proyecto Node.js El proyecto Node.js sigue una arquitectura modular. Cuando creamos un proyecto Node.js , significa crear un módulo. Este módulo debe tener un archivo de descripción, a saber, package.json . Es nuestro archivo de configuración más común, pero ¿realmente ha comprendido en detalle la configuración que contiene? Configurar un archivo package.json razonable determina directamente la calidad de nuestro proyecto, por lo que primero analizaremos la configuración detallada de package.json .
Hay muchos atributos en package.json , de los cuales solo se deben completar dos: name y version . Estos dos atributos forman el identificador único de un módulo npm .
name el nombre del módulo. Al nombrar, debe seguir algunas especificaciones y recomendaciones oficiales:
el nombre del paquete se convertirá en un parámetro en la url del módulo, la línea de comando o un nombre de url . están en el nombre del paquete. Ninguno de los dos se puede utilizar. Puede utilizar validate-npm-package-name para comprobar si el nombre del paquete es legal.
Los nombres semánticos de los paquetes pueden ayudar a los desarrolladores a encontrar los paquetes necesarios más rápidamente y evitar obtener accidentalmente el paquete incorrecto.
Si hay algunos símbolos en el nombre del paquete, los símbolos no deben repetirse con el nombre del paquete existente después de eliminarlos.
Por ejemplo: dado que react-native ya existe, react.native y reactnative no se pueden volver a crear.
Por ejemplo: el nombre de usuario es conard , luego el alcance es @conard y el paquete publicado puede ser @conard/react .
name es el identificador único de un paquete y no debe repetirse con otros nombres de paquete. Podemos ejecutar npm view packageName para ver si el paquete está ocupado y podemos ver información básica sobre él.

Si nunca se ha utilizado el nombre del paquete, se generará un error 404 :

Además, también puede ir a https://www.npmjs.com/ para obtener información más detallada sobre el paquete.
{
"description": "Un lenguaje de diseño de UI de clase empresarial e implementación de componentes React",
"palabras clave": [
"hormiga",
"componente",
"componentes",
"diseño",
"estructura",
"Interfaz",
"reaccionar",
"componente de reacción",
"interfaz de usuario"
]
} description se utiliza para agregar información de descripción del módulo para facilitar que otros comprendan su módulo.
keywords se utiliza para agregar palabras clave a su módulo.
Por supuesto, también juegan un papel muy importante, que es facilitar la recuperación del módulo. Cuando utiliza npm search para recuperar un módulo, coincidirá con description y keywords . Escribir una buena description y keywords ayudará a que su módulo obtenga una exposición cada vez más precisa:

describan a los desarrolladores: author y contributors . author se refiere al autor principal del paquete y un author corresponde a una persona. contributors se refieren a la información del contribuyente. Un contributors corresponde a varios contribuyentes. El valor es una matriz. La descripción de la persona puede ser una cadena o la siguiente estructura:
{.
"nombre": "ConardLi",
"correo electrónico": "[email protected]",
"url": "https://github.com/ConardLi"
} {
"página de inicio": "http://ant.design/",
"insectos": {
"url": "https://github.com/ant-design/ant-design/issues"
},
"repositorio": {
"tipo": "git",
"url": "https://github.com/ant-design/ant-design"
},
} homepage se utiliza para especificar la página de inicio de este módulo.
repository se utiliza para especificar el repositorio de código del módulo.

bugs especifica una dirección o un correo electrónico donde las personas que tengan preguntas sobre su módulo pueden acudir aquí para plantear preguntas.
Nuestro proyecto puede depender de uno o más paquetes de dependencias externos Según los diferentes usos de los paquetes de dependencia, los configuramos bajo los siguientes atributos: dependencies、devDependencies、peerDependencies、bundledDependencies、optionalDependencies .
Antes de presentar varias configuraciones de dependencia, primero echemos un vistazo a las reglas de configuración de dependencia. La configuración del paquete de dependencia que ve puede ser la siguiente:
"dependencias": {
"antd": "ant-design/ant-design#4.0.0-alpha.8",
"axios": "^1.2.0",
"test-js": "archivo:../prueba",
"test2-js": "http://cdn.com/test2-js.tar.gz",
"core-js": "^1.1.5",
} La configuración de dependencia sigue las siguientes reglas de configuración:
依赖包名称:VERSION VERSION es una configuración de número de versión que sigue SemVer . Cuando npm install irá al servidor npm para descargar paquetes que cumplan con el rango de versiones especificado.依赖包名称:DWONLOAD_URL DWONLOAD_URL es una dirección de paquete comprimido tarball descargable. Cuando se instala el módulo, este .tar se descargará e instalará localmente.依赖包名称:LOCAL_PATH LOCAL_PATH es una ruta de paquete de dependencia local, como file:../pacakges/pkgName . Adecuado para probar un paquete npm localmente; este método no debe aplicarse en línea.依赖包名称:GITHUB_URL GITHUB_URL es el método de escritura del username/modulename del módulo de github , por ejemplo: ant-design/ant-design . También puede especificar tag y commit id más adelante.依赖包名称:GIT_URL GIT_URL es git url de nuestra base de código de clonación habitual, que sigue el siguiente formato:<protocolo>://[<usuario>[:<contraseña>]@]<nombre de host>[:<puerto>] [: ][/]<ruta>[#<commit-ish> | #semver:<semver>]
protocal puede tener las siguientes formas:
git://github.com/user/project.git#commit-ishgit+ssh://user@hostname:project.git#commit-ishgit+ssh://user@hostname/project.git#commit-ishgit+http://user@hostname/project/blah.git#commit-ishgit+https://user@hostname/project/blah.git#commit-ishdependencies especifican los módulos de los que depende el proyecto. Tanto el entorno de desarrollo como los módulos de dependencia del entorno de producción se pueden configurar aquí, como
". dependencias": {
"lodash": "^4.17.13",
"momento": "^2.24.0",
} Hay algunos paquetes en que solo puede usar en el entorno de desarrollo, como eslint para verificar las especificaciones del código y jest para probar. Cuando los usuarios usan su paquete, puede ejecutarse normalmente incluso sin instalar estas dependencias. Tomará más tiempo y recursos, por lo que puede agregar estas dependencias a devDependencies . Estas dependencias aún se instalarán y administrarán cuando realice npm install localmente, pero no se instalarán en el entorno de producción:
"devDependencies": {
"broma": "^24.3.1",
"eslint": "^6.1.0",
} peerDependencies se utilizan para especificar la versión de la que depende el módulo que está desarrollando y la compatibilidad de la versión del paquete dependiente instalado por el usuario.
La declaración anterior puede ser demasiado abstracta. Tomemos ant-design como ejemplo. package.json de ant-design tiene la siguiente configuración:
"peerDependencies": {
"reaccionar": ">=16.0.0",
"react-dom": ">=16.0.0"
} Cuando estás desarrollando un sistema y usando ant-design , definitivamente necesitas confiar en React . Al mismo tiempo, ant-design también necesita confiar en React . React que necesita para mantener un funcionamiento estable es 16.0.0 , y la versión React en la que confía cuando desarrolla es 15.x :
en este momento, ant-design necesita usar React e importarlo:
import * as React from 'react'; import * as ReactDOM from 'react-dom';
lo que obtienes en este momento es el entorno de host, que es la versión React en tu entorno, lo que puede causar algunos problemas. En npm2 , especificar peerDependencies anteriores significará forzar al entorno host a instalar versiones de react@>=16.0.0和react-dom@>=16.0.0 .
En el futuro, npm3 ya no requerirá que los paquetes de dependencia especificados por peerDependencies se instalen por la fuerza. Por el contrario npm3 verificará si la instalación es correcta después de que se complete la instalación. Si es incorrecto, se imprimirá una advertencia para el usuario. .
"dependencias": {
"reaccionar": "15.6.0",
"antd": "^3.22.0"
} Por ejemplo, confío en la última versión de antd en el proyecto y luego confío en la versión 15.6.0 de react . Se dará la siguiente advertencia al instalar la dependencia:

En algunos escenarios, el paquete dependiente puede no ser una dependencia fuerte. La función de este paquete dependiente es prescindible. Cuando no se puede obtener este paquete dependiente, desea que npm install continúe ejecutándose sin causar fallas. optionalDependencies Tenga en cuenta que la configuración en optionalDependencies anulará dependencies por lo que solo es necesario configurarla en un lugar.
Por supuesto, al hacer referencia a dependencias instaladas en optionalDependencies , se debe realizar un manejo de excepciones; de lo contrario, se informará un error cuando no se pueda obtener el módulo.
es diferente de lo anterior. El valor de bundledDependencies es una matriz. Algunos módulos se pueden especificar en la matriz. Estos módulos se empaquetarán juntos cuando se lance este paquete.
"bundledDependencies": ["paquete1", "paquete2"]
{
"licencia": "MIT"
} El campo license se utiliza para especificar el acuerdo de código abierto del software. El acuerdo de código abierto detalla los derechos que otros tienen después de obtener su código, qué operaciones pueden realizar en su código y qué operaciones están prohibidas. Hay muchas variantes de un mismo acuerdo. Un acuerdo demasiado laxo hará que el autor pierda muchos derechos sobre la obra, mientras que un acuerdo demasiado estricto no será conveniente para los usuarios ni para la difusión de la obra. , los autores de código abierto deben considerar qué derechos quieren conservar y qué restricciones quieren flexibilizar.
Los acuerdos de software se pueden dividir en dos categorías: de código abierto y comerciales. Para los acuerdos comerciales, también llamados declaraciones legales y acuerdos de licencia, cada software tendrá su propio conjunto de texto, escrito por el autor del software o un abogado especializado. No es necesario dedicar tiempo y esfuerzo a redactar largos acuerdos de licencia. Elegir una licencia de código abierto de amplia circulación es una buena opción.
Los siguientes son varios protocolos principales de código abierto:

MIT : Siempre que los usuarios incluyan un aviso de copyright y un aviso de licencia en sus copias del proyecto, pueden hacer lo que quieran con su código sin ninguna responsabilidad de su parte.Apache : similar al MIT , pero también incluye términos relacionados con la concesión de licencias de patentes proporcionadas por los contribuyentes a los usuarios.GPL : Los usuarios que modifican el código del proyecto deben publicar sus modificaciones relevantes al redistribuir el código fuente o el código binario.Si tiene requisitos más detallados para el acuerdo de código abierto, puede ir a Choosealicense.com/ para obtener una descripción más detallada del acuerdo de código abierto.

{
"principal": "lib/index.js",
} El atributo main puede especificar el archivo de entrada principal del programa. Por ejemplo, la entrada del módulo lib/index.js especificada por antd anteriormente. Cuando introducimos antd en el código: import { notification } from 'antd'; lo que se introduce son lib/index.js .

Cuando su módulo es una herramienta de línea de comando, necesita especificar una entrada para la herramienta de línea de comando, es decir, especificar la correspondencia entre su nombre de comando y el archivo local especificable. Si se instala globalmente, npm usará un enlace simbólico para vincular el archivo ejecutable a /usr/local/bin . Si se instala localmente, se vinculará a ./node_modules/.bin/ .
{
"papelera": {
"conard": "./bin/index.js"
}
} Por ejemplo, la configuración anterior: Cuando su paquete se instala globalmente: npm creará un enlace suave llamado conard en /usr/local/bin , apuntando a "./bin/index.js" . En este momento, si ejecuta conard en la línea de comando, se llamará al archivo js vinculado.
No entraré en demasiados detalles aquí; se explicará más contenido en detalle en mis artículos posteriores sobre herramientas de línea de comandos.
{
"archivos": [
"distrito",
"lib",
"es"
]
} El atributo files se usa para describir la lista de archivos que envía al servidor npm después de npm publish . Si especifica una carpeta, se incluirá todo el contenido de la carpeta. Podemos ver que el paquete descargado tiene la siguiente estructura de directorios:

Además, también puede configurar un archivo
.npmignorepara excluir algunos archivos y evitar que una gran cantidad de archivos basura se envíen anpm. Las reglas son las mismas que.gitignoreque utiliza. Los archivos.gitignoretambién pueden actuar como archivos.npmignore.
El comando man es un comando de ayuda en Linux . A través del comando man , puede ver la ayuda del comando, la ayuda del archivo de configuración, la ayuda de programación y otra información en Linux .
Si su módulo node.js es una herramienta de línea de comando global, puede especificar la dirección del documento buscado por el comando man a través del atributo man en package.json .
Los archivos man deben terminar con un número o, si están comprimidos, .gz . El número indica en qué parte de man se instalará el archivo. Si el nombre del archivo man no comienza con el nombre del módulo, el nombre del módulo tendrá el prefijo durante la instalación.
Por ejemplo, la siguiente configuración:
{
"hombre" : [
"/Users/isaacs/dev/npm/cli/man/man1/npm-access.1",
"/Usuarios/isaacs/dev/npm/cli/man/man1/npm-audit.1"
]
} Ingrese man npm-audit en la línea de comando:

Se implementa un módulo node.js basado en CommonJS . En estricta conformidad con la especificación CommonJS , además del archivo de descripción del paquete package.json , el directorio del módulo también debe contener los siguientes directorios:
bin : donde. Se almacenan los archivos binarios ejecutables. Directoriolib : Directorio para almacenar el código js.doc : Directorio para almacenar documentos.test : Directorio para almacenar el código del caso de prueba unitariaEn el directorio del módulo, no puede seguir estrictamente la estructura anterior para organizarlo o nombrarlo. Puede especificar directories en las Propiedades package.json para especificar cómo la estructura de su directorio corresponde a la estructura canónica anterior. Aparte de esto, el atributo directories no tiene otras aplicaciones por el momento.
{
"directorios": {
"lib": "src/lib/",
"bin": "fuente/bin/",
"hombre": "fuente/hombre/",
"doc": "fuente/doc/",
"ejemplo": "src/ejemplo/"
}
} Sin embargo, el documento oficial indica que aunque este atributo actualmente no tiene un papel importante, es posible que se desarrollen algunos trucos en el futuro. Por ejemplo, los archivos de rebajas almacenados en doc y los archivos de ejemplo almacenados en example pueden mostrarse de manera amigable.
{
"guiones": {
"prueba": "jest --config .jest.js --no-cache",
"dist": "antd-tools ejecuta dist",
"compile": "antd-tools ejecuta la compilación",
"build": "npm ejecutar compilar && npm ejecutar dist"
}
} scripts se usa para configurar las abreviaturas de algunos comandos de script. Cada script se puede usar en combinación entre sí. Estos scripts pueden cubrir todo el ciclo de vida del proyecto. Después de la configuración, se pueden llamar usando npm run command . Si es una palabra clave npm , se puede llamar directamente. Por ejemplo, la configuración anterior especifica los siguientes comandos: npm run test , npm run dist , npm run compile , npm run build .
El campo config se usa para configurar las variables de entorno utilizadas en el script. Por ejemplo, la siguiente configuración se puede obtener usando process.env.npm_package_config_port en el script.
{
"config": { "puerto": "8080" }
} Si su módulo node.js se utiliza principalmente para instalar herramientas de línea de comandos globales, entonces este valor se establece en true y los usuarios recibirán una advertencia cuando instalen el módulo localmente. Esta configuración no impedirá que los usuarios realicen la instalación, pero les solicitará que eviten un uso incorrecto que pueda causar algunos problemas.
Si el atributo private se establece en true , npm se negará a publicarlo. Esto es para evitar que un módulo privado se publique accidentalmente.

"publicarConfig": {
"registro": "https://registry.npmjs.org/"
}, configuración más detallada al publicar el módulo, por ejemplo, puede configurar para publicar solo una determinada tag , configurar la fuente npm privada para publicar.
una configuración más detallada, consulte npm-config
Si desarrolla un módulo que solo puede ejecutarse en el sistema darwin , debe asegurarse de que los usuarios windows no instalen su módulo para evitar errores innecesarios.
El uso del os os puede ayudarle a cumplir los requisitos anteriores. Puede especificar que su módulo solo se pueda instalar en ciertos sistemas o especificar una lista negra de sistemas que no se pueden instalar:
"os": [ "darwin", "linux" ] "os" : [ "!win32" ]
Por ejemplo, asigno un módulo de prueba a una lista negra del sistema: "os" : [ "!darwin" ] Cuando lo instalo en este sistema, aparecerá el siguiente error:

En el entorno del nodo, puede utilizar Process.Platform para determinar el sistema operativo.
es similar al os anterior. Podemos usar el atributo cpu para limitar con mayor precisión el entorno de instalación del usuario:
"cpu": [ "x64", "ia32" ] "cpu" : [ "!arm", "!mips" ]
En el entorno del nodo, puede utilizar Process.arch para determinar la arquitectura de la CPU.
El éxito de Nodejs es inseparable del excelente sistema de gestión de dependencias de npm . Antes de presentar todo el sistema de dependencia, debe comprender cómo npm administra las versiones de los paquetes dependientes. Este capítulo presentará las especificaciones de lanzamiento de la versión de npm包, cómo administrar las versiones de varios paquetes dependientes y algunas de las mejores prácticas con respecto a las versiones de los paquetes.

Puede ejecutar npm view package version para ver la última versión de un package .
Ejecute npm view conard versions para ver todas las versiones publicadas de un package en el servidor npm.

Ejecute npm ls para ver la información de la versión de todos los paquetes en el árbol de dependencia del almacén actual.

Las versiones de los módulos en npm包deben seguir SemVer , una regla guía y unificada de representación del número de versión redactada por Github . En realidad es la abreviatura de Semantic Version .
Sitio web oficial de la especificación SemVer: https://semver.org/Standard
El número de versión estándar de SemVer adopta el formato XYZ , donde X, Y y Z son enteros no negativos y el relleno de ceros delante de los números es prohibido. X es el número de versión principal, Y es el número de versión secundaria y Z es el número de revisión. Cada elemento debe incrementarse numéricamente.
major ): cuando realiza modificaciones de API incompatibles.minor ): cuando realiza funcionalidades compatibles con versiones anteriores. Nuevopatch ): cuando realiza problemas de compatibilidad con versiones anteriores Corrección.Por ejemplo: 1.9.1 -> 1.10.0 -> 1.11.0
Cuando una versión tiene cambios importantes, no es estable y puede no cumplir con los requisitos de compatibilidad esperados, es posible que desee lanzar una versión avanzada primero.
El número de versión inicial se puede agregar al final de "número de versión principal. número de versión secundaria. número de revisión". Primero agregue un número de conexión y luego una serie de identificadores e información de compilación de versión separados por puntos.
alpha ):beta ):rc Release candiateEchemos un vistazo a las versiones históricas de React :

Se puede ver que la versión se publica estrictamente de acuerdo con SemVer :
主版本号.次版本号.修订号El nombre de16.8.0 -> 16.8.1 -> 16.8.216.8.0 -> 16.8.1 -> 16.8.2alpha beta , rc y otras versiones avanzadas. Después de modificar ciertas funciones del paquete npm , generalmente es necesario lanzar una. nueva versión. Nuestro enfoque habitual es modificar directamente package.json a la versión especificada. Si la operación es incorrecta, es fácil causar confusión en el número de versión. Podemos usar comandos que cumplan con Semver para completar esta operación:
npm version patch : actualice el número denpm version minor : actualice el número de versión menor denpm version major : actualice el número de versión principalen desarrollo es definitivamente indispensable para el funcionamiento de algunos números de versión. Si estos números de versión cumplen con la especificación SemVer , podemos usar el paquete npm semver para operar versiones para ayudarnos. comparar tamaños de versiones, extraer información de versiones y otras operaciones.
Npm también utiliza esta herramienta para manejar el trabajo de control de versiones.
npm install semver
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // verdadero semver.valid('1.2.3') // '1.2.3'
semver.valid('abc') // null semver.valid(semver.coerce('v2')) // '2.0.0'
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // semver.clean(' =v1.2.3 ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // verdadero
semver.minVersion('>=1.0.0') // '1.0.0' Los anteriores son los usos más comunes de semver. Para obtener más detalles, consulte la documentación de semver: https://github.com/npm/node. -semver
A menudo vemos diferentes formas de escribir varias dependencias en package.json :
"dependencias": {
"señal": "1.4.0",
"figlet": "*",
"reaccionar": "16.x",
"tabla": "~5.4.6",
"yargs": "^14.0.0"
} Los primeros tres son fáciles de entender:
"signale": "1.4.0" : Número de versión fijo"figlet": "*" : Cualquier versión ( >=0.0.0 )"react": "16.x" : Coincidencia Versión principal ( >=16.0.0 <17.0.0 )"react": "16.3.x" : Coincide con la versión principal y la versión secundaria ( >=16.3.0 <16.4.0 )Echemos un vistazo a las dos últimas, la número de versión Los símbolos ~ y ^ están entrecomillados:
~ : Cuando se obtiene una nueva versión al instalar dependencias, instale la última versión de z en xyz . Es decir, aunque se mantienen sin cambios el número de versión principal y el número de versión secundaria, se mantiene el número de revisión más reciente.^ : Cuando se obtiene una nueva versión al instalar dependencias, tanto y como z en xyz instaladas son las últimas versiones. Es decir, manteniendo el número de versión principal sin cambios, mantenga el número de versión secundaria y el número de revisión como la última versión.La dependencia más común en el archivo package.json debería ser "yargs": "^14.0.0" , porque cuando usamos npm install package para instalar el paquete, npm instala la última versión de forma predeterminada y luego la instala en Agregar un signo ^ antes del número de versión.
Tenga en cuenta que cuando el número de versión principal es 0 , se considerará una versión inestable. La situación es diferente a la anterior:
0 : ^0.0.z y ~0.0.z son ambos. Consideradas como versiones fijas, no se producirán cambios al instalar dependencias.0 : ^0.yz se comporta igual que ~0.yz , solo el número de revisión se mantiene como la última versión.El número de versión 1.0.0 se utiliza para definir la API pública. Cuando su software se lance al entorno oficial o tenga una API estable, podrá lanzar la versión 1.0.0. Entonces, cuando decida lanzar una versión oficial de un paquete npm al mundo exterior, marque su versión como 1.0.0.
En el desarrollo real, a menudo ocurren problemas extraños debido a inconsistencias en varias dependencias o, en algunos escenarios, no queremos que las dependencias se actualicen. Se recomienda usar package-lock.json durante el desarrollo.
Bloquear la versión de la dependencia significa que, a menos que realicemos actualizaciones manualmente, la versión fija se instalará cada vez que instalemos la dependencia. Asegúrese de que todo el equipo utilice dependencias con números de versión consistentes.
Cada vez que instala una versión fija, no es necesario calcular el rango de versiones de dependencia, lo que puede acelerar enormemente el tiempo de instalación de la dependencia en la mayoría de los escenarios.
Cuando utilice package-lock.json, asegúrese de que la versión npm sea superior a 5.6, porque entre 5.0 y 5.6, la lógica de procesamiento de package-lock.json se actualizó varias veces y la lógica de posprocesamiento de la versión 5.6 se estabilizó gradualmente.
Analizaremos la estructura detallada de package-lock.json en capítulos posteriores.
Nuestro propósito de
En escenarios de desarrollo reales, aunque no necesitamos instalar una nueva versión cada vez, aún necesitamos actualizar las versiones de dependencia regularmente para que podamos disfrutar de las correcciones de problemas, mejoras de rendimiento y nuevas actualizaciones de funciones generadas por las actualizaciones de paquetes de dependencia.

El uso de npm outdated puede ayudarnos a enumerar las dependencias que no se han actualizado a la última versión:
y ejecutar npm update Actualice todas las dependencias rojas.
1.0.0 .主版本号.次版本号.修订号alpha、beta、rc y. otras versiones avanzadas primeronpm desarrollados por miembros del equipo. En este momento, se recomienda cambiar el prefijo de versión ~ . Las dependencias del proyecto principal deben actualizarse cada vez que se actualizan las subdependencias, lo cual es muy engorroso. Si las subdependencias son completamente confiables, ábralas directamente ^ Actualice a la última versión cada vez.docker y las subdependencias aún se están desarrollando y actualizando localmente. Antes de que se lance la versión docker , todas las versiones de las dependencias deben bloquearse para garantizar que no haya problemas en línea después de que se publiquen las subdependencias locales. liberado.npm sea superior a 5.6 y asegúrese de que el archivo package-lock.json esté habilitado de forma predeterminada.npm inatall , package-lock.json se envía al almacén remoto. No envíe node_modules directamente al repositorio remoto.npm update para actualizar las dependencias y envíe el archivo lock para garantizar que otros miembros actualicen sus dependencias simultáneamente. No cambie el archivo lock manualmente.lockpackage.json y ejecute npm installnpm install package@version (cambiar package.json no degradará las dependencias).
npm install probablemente pasará por los procesos anteriores. Este capítulo hablará sobre los detalles de implementación, el desarrollo y el por qué de cada proceso.
Todos sabemos que después de ejecutar npm install , los paquetes dependientes se instalan en node_modules . Echemos un vistazo más de cerca al mecanismo específico mediante el cual npm instala paquetes dependientes en node_modules .
En las primeras versiones de npm , la forma en que npm manejaba las dependencias era simple y tosca: instalaba dependencias en sus respectivos node_modules de manera recursiva y estrictamente de acuerdo con la estructura package.json y la estructura package.json de los paquetes de subdependencia. Hasta que haya paquetes subdependientes que ya no dependan de otros módulos.
Por ejemplo, nuestro módulo my-app ahora depende de dos módulos: buffer e ignore :
{
"nombre": "mi-aplicación",
"dependencias": {
"búfer": "^5.4.3",
"ignorar": "^5.1.4",
}
} ignore es un módulo JS puro que no depende de ningún otro módulo, y buffer depende de los dos módulos siguientes: base64-js e ieee754 .
{
"nombre": "búfer",
"dependencias": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4"
}
} Luego, después de ejecutar npm install , la estructura del directorio del módulo en node_modules obtenida es la siguiente:

Las ventajas de este método son obvias: la estructura de node_modules corresponde a la estructura de package.json uno a uno, la estructura jerárquica es obvia y se garantiza que la estructura de directorios de cada instalación será la misma.
Sin embargo, imagínese, si depende de muchos módulos, sus node_modules serán muy grandes y el nivel de anidamiento será muy profundo:

Windows , la longitud máxima de la ruta del archivo es de 260 caracteres y un nivel de anidamiento demasiado profundo puede causar problemas impredecibles.Para resolver los problemas anteriores, NPM realizó una actualización importante en la versión 3.x Cambia la estructura anidada inicial a una estructura plana:
node_modules .Aún con la estructura de dependencia anterior, obtendremos la siguiente estructura de directorios después de ejecutar npm install :


En este momento, si confiamos en la versión [email protected] en el módulo:
{
"Nombre": "my-app",
"dependencias": {
"buffer": "^5.4.3",
"ignorar": "^5.1.4",
"Base64-JS": "1.0.1",
}
} node_modules la versión del módulo instalado coincide con el rango de versión del nuevo módulo, omita.En este punto, obtendremos la siguiente estructura del directorio después de ejecutar npm install :


En consecuencia, si hacemos referencia a un módulo en el código de proyecto, el proceso de búsqueda del módulo es el siguiente:
node_modulesnode_modules .node_modules rutabuffer2@^5.4.3 [email protected]

Por lo tanto, la versión npm 3.x no resuelve completamente el problema de redundancia del módulo de la versión anterior, e incluso puede traer nuevos problemas.
Imagine que su aplicación no depende de la versión [email protected] , pero también depende de buffer y buffer2 que dependa de diferentes versiones base64-js .
buffer2
npm install , las dependencias en package.json se analizan en orden, el orden en el que buffer y buffer2 se colocan en node_modules package.json

Depende primero de buffer :

Además, para permitir a los desarrolladores usar los últimos paquetes de dependencia bajo la premisa de seguridad, generalmente solo bloqueamos la versión grande en package.json , lo que significa que después de actualizar la versión menor de algunos paquetes de dependencia, la estructura de dependencia puede también cambiar.
Para resolver el problema de incertidumbre de npm install , el archivo package-lock.json se agregó en la versión npm 5.x , y el método de instalación también sigue el método plano de npm 3.x
La función de package-lock.json package-lock.json npm install la estructura de node_modules . .
Por ejemplo, tenemos la siguiente estructura de dependencia:
{
"Nombre": "my-app",
"dependencias": {
"buffer": "^5.4.3",
"ignorar": "^5.1.4",
"Base64-JS": "1.0.1",
}
} package-lock.json generado después de ejecutar npm install es el siguiente:
{
"Nombre": "my-app",
"versión": "1.0.0",
"dependencias": {
"Base64-JS": {
"Versión": "1.0.1",
"Resuelto": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz",
"Integridad": "SHA1-ASBRSZT7XZE47TUTDW3I/NP+PAG ="
},
"Buffer": {
"Versión": "5.4.3",
"Resuelto": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz",
"Integridad": "SHA512-ZVJ65TKFEIT3I6AJ5BIVJDZJJJQQGS4O/SNOEZG1F1KYAP9NU2JCUDPWZRSJTHMMZG0H7BZKN4RNQPIMHUXWX2A ==",
"Requiere": {
"Base64-JS": "^1.0.2",
"IEEE754": "^1.1.4"
},
"dependencias": {
"Base64-JS": {
"Versión": "1.3.1",
"Resuelto": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"Integridad": "SHA512-MLQ4I2QO1YTVGWFWMCNGKO // JXAQUEZVWEKTJGQFM4JIK0KU+YTMFPLL8J+N5MSPOFJHWOAG+9YHB7BWAHM36G =="
}
}
},
"IEEE754": {
"Versión": "1.1.13",
"Resuelto": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
"Integridad": "SHA512-4VF7I2LYV/Hawersso3XMLMKP5EZ83I+/CDLUXI/IGTS/O1SEJBNHTTNXZMRZFVOUQJ7LZJQHKETVPGSFDLWZTG =="
},
"ignorar": {
"Versión": "5.1.4",
"Resuelto": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz",
"Integridad": "SHA512-MZBUSAHKTW1U7JPKKJY7LCARD1FU5W2RLDXLM4KDKAYUCWZIMJKPLUF9CM1ALEWYJGUPDQEWLAM18Y6AU69A8A =="
}
}
} Echemos un vistazo más de cerca a la estructura anterior:

name y version de los dos atributos más externos son los mismos que name y version en package.json , y se utilizan para describir el nombre y la versión actuales del paquete.
dependencies es key objeto, que corresponde a la estructura del node_modules
resolvedversion node_modulesdependencies requiresintegrity hash Subresource Integrity sido modificado o inválido.package.json dependencia.json.dependencies : la estructura es la misma que la estructura dependencies externas, y almacena los paquetes de dependencia instalados en el node_modules de subdependencia.Tenga en cuenta aquí que no todas las subdependencias tienen el atributo dependencies node_modules
Por ejemplo, revise las dependencias anteriores:

La versión [email protected] en la que confiamos en my-app conflictos con base64-js@^1.0.2 Confiamos en buffer , por lo que [email protected] debe instalarse en node_modules de los El paquete buffer , correspondiente al atributo de dependencies de buffer en package-lock.json se ha cambiado. Esto también corresponde al enfoque plano de npm a las dependencias.
Por lo tanto, de acuerdo con el análisis anterior, package-lock.json package-lock.json node_modules están en correspondencia individual. generado por cada instalación igual.
Además, el uso de package-lock.json en el proyecto puede acelerar significativamente el tiempo de instalación de dependencia.
Usamos el comando npm i --timing=true --loglevel=verbose lock lock el proceso completo de npm install . Limpie el caché npm antes de comparar.
Sin usar el archivo lock :

Use el archivo lock :

Se puede ver que la versión específica y el enlace de descarga de cada paquete se han almacenado en caché en package-lock.json . Gran cantidad de solicitudes de red.
para desarrollar aplicaciones del sistema, se recomienda enviar el archivo package-lock.json al repositorio de la versión de código para garantizar que las versiones de dependencia instaladas por todos los desarrolladores de equipos y los enlaces CI sean consistentes al ejecutar npm install .
Al desarrollar un semver npm , su paquete npm debe depender de otros repositorios. Dentro del alcance, que causará redundancia innecesaria. Por lo tanto, no debemos publicar el archivo package-lock.json ( npm no publicará package-lock.json de forma predeterminada).
Después de ejecutar el comando npm install o npm update para descargar dependencias, además de instalar el paquete de dependencia en el directorio node_modules , una copia también se almacenará en caché en el directorio de caché local.
Puede consultarlo a través npm config get cache : en Linux o Mac el valor predeterminado es el directorio .npm/_cacache en el directorio de inicio del usuario.
Hay tar directorios en este directorio hash content-v2 content-v2 y index-v5 tar index-v5
Cuando NPM está ejecutando la instalación, puede generar una key única correspondiente al registro de caché en el directorio index-v5 en función de integrity、version、name almacenado en package-lock.json , encontrando así hash del paquete tar , y luego buscarlo en base hash tar
Podemos encontrar un paquete para buscar y probar en el directorio de caché, y buscar la ruta del paquete en index-v5 :
grep "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1. tgz "-r índice -v5

Entonces formatamos el JSON:
{
"Clave": "Pacote: Version-Manifest: https: //registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz: sha1-asbrszt7xze47tutdw3i/np+pag =",,,
"Integridad": "SHA512-C2EKHXWXVLSBRUCJTRS3XFHV7MF/Y9KLMKDXPTE8YEVCOH5H8AE69Y+/LP+AHPW91CRNZGO78ELOK2E6APJFIQ ==",,,
"Tiempo": 1575554308857,
"Tamaño": 1,
"Metadatos": {
"ID": "[email protected]",
"manifiesto": {
"Nombre": "Base64-JS",
"Versión": "1.0.1",
"Motores": {
"nodo": "> = 0.4"
},
"Dependencias": {},
"OppectionDependencies": {},
"Devdependencias": {
"estándar": "^5.2.2",
"cinta": "4.x"
},
"BundledEpendencias": Falso,
"PeerDependencies": {},
"Deprecido": Falso,
"_RESOLVED": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz",
"_integrity": "Sha1-ASBRSZT7XZE47TUTDW3I/NP+PAG =",
"_shasum": "6926d1b194fbc737b8eed513756de2fcda7ea408",
"_shrinkwrap": nulo,
"Bin": Null,
"_id": "[email protected]"
},
"Tipo": "Finalizado-manifestación"
}
} El atributo _shasum anterior 6926d1b194fbc737b8eed513756de2fcda7ea408 es hash del paquete tar , y los primeros dígitos 6926 del hash son los primeros dos niveles de directorios caché

La estrategia de almacenamiento en caché anterior comienza desde la versión NPM V5. }.
npm proporciona varios comandos para administrar datos de caché:
npm cache add : La explicación oficial es que este comando es utilizado internamente internamente por npm , pero también se puede usar para agregar manualmente un caché a un paquete especificado.npm cache clean : elimine todos los datos en el directorio de caché --forcenpm cache verify : Verifique la validez e integridad de los datos en caché y limpie los datos basura.Según los datos en caché, NPM proporciona modos de instalación fuera de línea, que son los siguientes:
--prefer-offline : Use los datos en caché primero.--prefer-online : priorice el uso de datos de red.--offline : no solicite la red y use los datos en caché directamente.mencionamos la integridad de archivos muchas veces arriba, entonces, ¿qué es la verificación de integridad de archivos?
Antes de descargar el paquete de dependencia, generalmente podemos obtener hash calculado por npm para el paquete de dependencia, por ejemplo, si ejecutamos el comando npm info , el shasum ( hash ) seguido por el tarball (HASH).

hash de que el usuario descarga el paquete de dependencia localmente, debe asegurarse hash que no se produzcan errores durante el proceso de descarga. Son los mismos, asegúrese de que la dependencia descargada esté completa.
Ahora que el proceso general está completo, resumamos el proceso anterior:
verifique el archivo .npmrc : la prioridad es: archivo de nivel .npmrc > archivo de nivel de usuario .npmrc > archivo de nivel global .npmrc > npm incorporado .npmrc
COMPRUEBE si hay un archivo lock en el proyecto.
Sin archivo lock :
npmpackage.json . node_modules .node_modules del módulo actual.npm el paquete de descarga de almacén remotonpmnode_modules de acuerdo con la estructura de dependencia .node_modulesnode_moduleslocklock
package.json package-lock.json .
El proceso anterior describe brevemente el proceso general de npm install npm install package --timing=true --loglevel=verbose proceso de instalación y detalles de un paquete determinado.

yarn se lanzó en 2016 En ese momento, npm todavía estaba package-lock.json V3 . de desarrolladores. En este punto, nace yarn :

Las anteriores son las ventajas de yarn mencionadas en el sitio web oficial, que todavía eran muy atractivos en ese momento. Por supuesto, npm luego se dio cuenta lock sus yarn yarn e hizo muchas optimizaciones. El diseño sigue siendo muy bueno.
de
yarn npm v3 para yarn.lock las yarn.lock .
Es un archivo autogenerado. # hilo Lockfile V1 [email protected]: Versión "1.0.1" resuelto "https://registry.yarnpkg.com/base64-js/-/base64-js-1.0.1.tgz#6926d1b194fbc737b8eed513756de2fcda7ea408" Integridad SHA1-ASBRSZT7XZE47TUTDW3I/NP+PAG = base64-js@^1.0.2: Versión "1.3.1" resuelto "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" "" Integridad SHA512-MLQ4I2QO1YTVGWFWMCNGKO // JXAQUEZVWEKTJGQFM4JIK0KU+YTMFPLL8J+N5MSPOFJHWOAG+9YHB7BWAHM36G == buffer@^5.4.3: Versión "5.4.3" resuelto "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" Integridad SHA512-ZVJ65TKFEIT3I6AJ5BIVJDZJJQQGS4O/SNOEZG1F1KYAP9NU2JCUDPWZRSJTHMMZZG0H7BZKN4RNQPIMHUXWX2A == dependencias: base64-js "^1.0.2" IEEE754 "^1.1.4" ieee754@^1.1.4: Versión "1.1.13" resuelto "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aaa181fd87d37f55c32bbcb6708b84" " Integridad Sha512-4vf7i2Lyv/Hawersso3XMLMKP5EZ83I+/CDLUXI/IGTS/O1SEJBNHTTNXZMRZFVOUQJ7LZJQHKETVPGSFDLWZTG == ignorar@^5.1.4: Versión "5.1.4" resuelto "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf"Integridad SHA512
package-lock.json
MZBUSAHKTW1U7JPKKJY7LCARD1FU5W2RLDXLM4KDKAYUCWZIMJKKPLUF9CM1ALEWYJGUPDQEWLAM18Y6AU69A8A
yarn.lock package-lock.json jsonyarn.lock El número de versión de yarn.lock no se fija, lo que significa que yarn.lock solo no puede determinar node_modules y debe coordinarse con el archivo package.json . Y package-lock.json solo necesita un archivo para determinar.La estrategia de almacenamiento en caché de yarn se ve muy similar a la de npm v5 . Use el yarn cache dir de comando para ver el directorio de datos en caché:

De forma predeterminada,
yarnusa el modoprefer-online, lo que significa que los datos de la red se usan primero.
Espero que después de leer este artículo, lo ayude de la siguiente manera:
pacakge.json para tener más información sobre la configuración de ingeniería de proyectosnpm versionesnpm install npm package-lock.json