javascript - node - npm last version
Construir automáticamente el módulo NPM en la instalación desde Github (2)
Suponiendo que haya un script de
build
dentro del campo de scripts del archivo package.json, ¿se puede configurar el paquete para que se ejecute automáticamente en esta situación?
Sí. Hay 2 cosas que debes hacer:
Asegúrese de que su sistema use
npm
oyarn
para instalar el paquete desde GitHub. Si este paquete es una dependencia de otro paquete, puede usar la URL de GitHub en lugar del número de versión enpackage.json
. De lo contrario, el siguiente comando funcionará:npm install https://github.com/YourUser/your-package
Puedes agregar
/tags/v1.0.0
o lo que sea al final de la URL si buscas una etiqueta o rama específica.Agregue lo siguiente a los
scripts
en elpackage.json
su módulo:"install": "npm run build"
install
es un gancho que el administrador de paquetes ejecuta después de instalar el módulo. ( preinstall
y postinstall
también - ver documentación).
Documentación: https://docs.npmjs.com/misc/scripts
Dado que lib/
dir de un proyecto no se debe registrar en Git porque los archivos que contiene son archivos derivados (del proceso de compilación). Al instalar un paquete desde el github del proyecto (durante el desarrollo, por ejemplo), no existirá lib/
dir, por lo que si el campo main
package.json
del paquete apunta a (por ejemplo) lib/index.js
, el paquete no se puede compilar cuando se importa porque estos archivos no existen dentro del repositorio y, por lo tanto, dentro del paquete instalado en los node_modules
. Esto significa que el paquete necesita compilación (tal como sería antes del lanzamiento), solo esta vez localmente para que el directorio lib
(o cualquier otro archivo que se genere durante el proceso de compilación) se agregue al directorio del módulo.
Suponiendo que haya un script de build
dentro del campo de scripts
del archivo package.json
, ¿se puede configurar el paquete para que se ejecute automáticamente en la situación en la que se instala solo desde github? Si no, ¿cuál es el mejor enfoque para garantizar que se construya cuando se instala desde github?
Ahora hay prepublish
, prepublishOnly
y prepare
enlaces de ciclo de vida, pero ninguno proporciona una respuesta a este problema porque no permiten de ninguna manera diferenciar entre la fuente de la instalación. En resumen, sí, te permiten compilar en la instalación, pero no te permiten compilar solo desde la instalación de github. No solo no hay razón para forzar una compilación cuando la gente instala desde npm, sino que lo más importante es que no se instalarán las dependencias de desarrollo (por ejemplo, babel
que es fundamental para la compilación).
Soy consciente de una estrategia para hacer frente a este problema:
- Tenedor / rama el repositorio
- construir localmente
- quite el
lib/
dir de.gitignore
y regístrelo. - Instala el módulo desde tu fork / rama.
- Cuando esté listo para un PR / rebase, agregue
lib/
dir a.gitignore
y elimine dir de git.
Pero eso está lejos de ser lo ideal. Aunque supongo que esto podría ser automatizado con un githook. Así que cada vez que presionas para dominar el proyecto también se construye y se empuja a una rama separada.
Hay un problema cerrado en el Github de NPM sin resolución, solo muchas personas que quieren una solución. De este problema queda claro que el uso de la prepare
no es la respuesta.
Mi caso de uso es que estoy desarrollando un módulo que se utiliza en otros proyectos. Quiero consumir la última versión del módulo sin tener que enviar un lanzamiento a NPM cada vez que actualizo el código base. Prefiero eliminar menos lanzamientos cuando esté listo, pero todavía necesito consumir la versión más reciente de la biblioteca. está en Github.
Nota: También contacté al soporte de NPM con respecto a este problema y agregaré su respuesta si recibo una.
Edición: Detectar si el paquete se está instalando desde git repo
No entendí la pregunta correctamente. A continuación hay cosas que escribí pero están un poco fuera de tema. Por ahora, si desea ejecutar build.js solo al instalar desde repo:
Archivos en repo:
.gitignore
.npmignore
ThisIsNpmPackage
build.js
package.json
El .gitginore
:
ThisIsNpmPackage
El .npmignore
:
!ThisIsNpmPackage
En el package.json:
"scripts": {
"install": "( [ ! -f ./ThisIsNpmPackage ] && [ ! -f ./AlreadyInstalled ] && echo /"/" > ./AlreadyInstalled && npm install . && node ./build.js ) || echo /"SKIP: NON GIT SOURCE/""
}
La idea es hacer que el archivo ThisIsNpmPackage
esté disponible en el repositorio, pero no en el paquete npm.
El gancho de instalación es solo una parte del script bashy para verificar si existe el ThisIsNpmPackage
. Si es así, entonces ejecutamos npm install .
(Esto asegurará que tengamos devDependencies
. El archivo ya AlreadyInstalled
se genera para evitar un bucle infinito (la instalación npm invocará recursivamente el gancho de instalación)
Cuando npm publish
hago git push
y npm publish
Tenga en cuenta que npm publish puede automatizarse a través de herramientas CI - githooks
Este pequeño truco con el archivo ThisIsNpmPackage
hace que la detección de la fuente esté disponible.
Resultados de invocar npm install dumb-package
:
"SKIP: FUENTE NO GIT"
Y ejecutando npm install https://github.com/styczynski/dumb-package
Los archivos serán construidos
Los problemas
Los principales problemas que enfrentamos aquí son los siguientes:
Tienes que hacer
npm publish ...
cada vez.
A veces es demasiado dolor corregir un error pequeño, luego presionar el repositorio y olvidarse de publicar en npm. Cuando trabajaba con un proyecto basado en microservicios que tiene alrededor de 5 subproyectos independientes divididos en módulos, el problema es que encontré un problema, lo solucioné y me olvidé de publicar en todos los lugares que tenía que ser realmente molesto.No quiero empujar
lib
en el repositorio, porque se deriva de fuentesRebasar y fusionar es aún más molesto.
No te metas con
.gitgnore
¿Sabes, ese es el problema cuando tienes algunos archivos que debes incluir dentro del repositorio pero nunca los modificas, o algunas veces eliminas? Eso es sólo enfermo.
Edición: npm ganchos
Como mencionó @Roy Tinker, existe la posibilidad de que un paquete ejecute un comando cuando se instala.
Se puede lograr a través de npm ganchos.
"install": "npm run build"
Y ejecutamos el:
npm install https://github.com/<user>/<package>
Editar:
Pregunta OP de los comentarios:
Pero esto ejecutará una instalación para todos los que descarguen el módulo desde npm, ¿no? Esto es muy problemático dado que las dependencias de desarrollo no se instalarán para nadie que descargue el módulo desde npm. Las bibliotecas utilizadas para compilar la aplicación - babel, etc. no se instalarán.
Nota: Pero si desea una versión específica del paquete (producción / dev) con o sin dependencias de desarrollo, puede instalarlo a través de:
npm install --only=dev
El argumento --only = {prod [uction] | dev [elopment]} provocará que se instalen solo devDependencies o solo no dev devendendencies, independientemente del NODE_ENV.
Una mejor solución en mi opinión es usar:
npm install <git remote url>
Y luego dentro de package.json especifique:
"scripts": {
"prepare": "npm run build"
}
Si el paquete que se está instalando contiene una secuencia de comandos de preparación, se instalarán sus dependencias y devoluciones, y se ejecutará la secuencia de comandos de preparación, antes de que el paquete sea empaquetado e instalado.
Ejemplo:
npm install git+https://[email protected]/npm/npm.git
Lea la documentación de npm allí: npm install
Edición: módulo proxy (técnica avanzada)
Es una mala práctica, pero es bueno saberlo.
A veces (como en el caso de Electron framework , necesita instalar otros paquetes externos o recursos / módulos dependiendo de varias condiciones).
En estos casos se utiliza la idea de proxy:
- Usted crea un módulo que se comporta como un instalador e instala todas las cosas que desee
En su caso, preparar el script será suficiente, pero dejo esta opción, porque a veces puede ser útil.
La idea es que escribas un módulo y escribas un kook de instalación para él :
"scripts": {
"install": "<do the install>"
}
En este escenario puedes colocar allí:
npm install . && npm run build
El cual instala todas las Dependencias de Dev de todos modos (como se mencionó anteriormente, prepara el caso), pero es un poco de piratería.
Si quieres hacer el verdadero hacking allí:
"scripts": {
"install": "curl -L -J -O /"<some_url>/""
}
que descarga archivos manualmente usando el comando -nix curl
Debe evitarse, pero es una opción en el caso de un módulo que tiene archivos binarios enormes para cada plataforma y no desea instalarlos todos.
Como en el caso de Electron donde ha compilado archivos binarios (cada uno para una plataforma separada)
Así que quieres que la gente haga que el install package
install package-linux
no install package-linux
o package-window
etc.
Por lo tanto, proporciona un script de install
personalizado en package.json
{
...
"scripts": {
"install": "node ./install_platform_dep.js"
}
}
Luego, al instalar el module
, se ejecutará el script install_platform_dep.js
. Dentro de install_platform_dep.js
coloca:
// For Windows...
if(process.platform === ''win32'') {
// Trigger Windows module installation
exec(''npm install fancy-module-windows'', (err, stdout, stderr) => {
// Some error handling...
}
} else if ... // Process other OS''es
Y esto de manera puramente manual lo instala todo.
Nota: una vez más, este enfoque se puede utilizar con módulos que dependen de la plataforma y, si lo usa, probablemente sea un problema de diseño con su código.
Integracion circular
Lo que me viene a la mente es la solución que usé realmente durante un tiempo de registro (creación automática con servicios de CI).
El propósito principal de la mayoría de los servicios de CI es probar / construir / publicar su código cuando se desplaza a la sucursal o realiza otras acciones con el repositorio.
La idea es que proporcione un archivo de configuración (como travis.yml o .gitlab-ci.yml ) y las herramientas se encarguen del resto.
Si realmente no desea incluir el lib en el proyecto, solo confíe en CI para hacer todo:
- Githook activará la creación de un compromiso (en una rama o en cualquier otro, es solo una cuestión de configuraciones)
- CI construirá sus archivos y luego los pasará a la fase de prueba y los publicará.
Ahora estoy trabajando en Gitlab en mi propio proyecto haciendo (como parte de un hobby) alguna página web. La configuración de Gitlab que construye el proyecto se ve así:
image: tetraweb/php
cache:
untracked: true
paths:
- public_html/
- node_modules/
before_script:
- apt-get update
stages:
- build
- test
- deploy
build_product:
stage: build
script:
- npm run test
build_product:
stage: build
script:
- npm run build
deploy_product:
stage: deploy
script:
- npm run deploy
Cuando me fusiono en la rama principal, suceden los siguientes eventos:
- CI ejecuta la etapa de
build
- Si la compilación tiene éxito, entonces se inicia la etapa de
test
- Si la fase de
test
está bien, finalmente se activa ladeploy
la etapa
El script es la lista de comandos de unix a ejecutar.
Puede especificar cualquier imagen de Docker en la configuración, así que use de hecho cualquier versión de Unix que desee con algunas (o no) herramientas preinstaladas.
No existe ningún problema para agregar comandos para insertar la compilación en otra rama.
Hay un paquete deploy-to-git que implementa artefactos en la rama de repo deseada.
O aquí (para Travis CI) la pieza de configuración que publica artefactos para repo:
(Lo utilicé por mi cuenta)
Luego, por supuesto, puedes dejar que CI ejecute:
npm publish .
Debido a que CI ejecuta comandos de Unix, entonces puede (al menos un grupo de proveedores de CI allí):
- Publicar etiquetas (¿etiqueta de liberación quizás?)
- Trigger script para actualizar la versión del proyecto en todos los READMEs y en todas partes
- Enviarle notificación si todas las fases tuvieron éxito
Entonces, lo que hago:
Me comprometo, presiono y dejo que las herramientas hagan todo lo que quiero.
Mientras tanto, realizo otros cambios y después de uno a diez minutos recibo el informe de actualización por correo.
Hay muchos proveedores de CI allí:
Aquí adjunto otro ejemplo de mi otro proyecto ( .travis.yml ):
language: generic
install:
- npm install
script:
- chmod u+x ./utest.sh
- chmod u+x ./self_test/autodetection_cli/someprogram.sh
- cd self_test && bash ../utest.sh --ttools stime --tno-spinner
Si configura CI para enviar y publicar su paquete, siempre puede estar seguro de usar la última versión de su código sin tener que preocuparse de si tengo que ejecutar también este comando ahora ... problema.
Te recomiendo que elijas uno de los proveedores de CI por ahí.
Los mejores te ofrecen cientos de habilidades!
Cuando te acostumbras a hacer automáticamente las fases de publicación, prueba y construcción, verás cómo te ayuda disfrutar de la vida.
Luego, para iniciar otro proyecto con scripts automáticos, ¡simplemente copie las configuraciones!
Resumen
En mi opinión npm prepare script es una opción.
Quizás también quieras probar con otros.
Cada uno de los métodos descritos tiene sus inconvenientes y se puede utilizar dependiendo de lo que desee lograr.
¡Solo quiero ofrecer algunas alternativas y espero que algunas de ellas se ajusten a tu problema!
Espero haberte ayudado un poco.
¡Que tengas un buen día!