compositor vs npm: desarrollo de módulos múltiples

En los últimos tres o cuatro años, cuando programaba en PHP, utilicé composer para administrar las dependencias de las aplicaciones. Ahora es necesario cambiar a nodejs y, como resultado, configurar un entorno de desarrollo familiar. Afortunadamente, uso el IDE de PhpStorm, que le permite trabajar con PHP y JS. Una característica de los proyectos en los que participo es la modularidad múltiple. La funcionalidad se divide entre los módulos, no tanto para su reutilización como para reducir la complejidad final de la aplicación debido a la descomposición en componentes sueltos. En general, es normal para estos proyectos cuando, en el marco de la resolución de un problema, se realizan cambios en varios módulos y se comprometen a varios repositorios.


imagen


Al configurar un proyecto de nodejs , me encontré con algunas características que complican el desarrollo de múltiples módulos. Esta publicación nació en el proceso de tratar de lidiar con estas características. Debajo del corte, la mirada de PHP en la implementación de un proyecto nodejs .


Estructura del proyecto de demostración


El proyecto consta de 3 módulos:


  • aplicación : módulo principal conectando dependencias;
  • módulo funcional : contiene funciones llamadas desde el módulo principal;
  • módulo base : contiene funciones llamadas desde un módulo de funciones;

imagen


El código para cada módulo se encuentra en github:



Los descriptores de módulo para los respectivos administradores de dependencias ( composer.json y package.json ) se encuentran en cada módulo, es decir, cada módulo se puede expandir como un módulo php y como un módulo js. El código PHP y el código JS en los módulos simplemente se colocan uno al lado del otro, sin cruzarse entre sí.


Ejecutando la aplicación para su ejecución:


 $ php index.php $ nodejs index.js 

El resultado del trabajo en ambos casos:


 This is application. This is func module. This is base module. 

Objetivos


Un proyecto en un entorno de trabajo debería permitir:


  • rastrear los cambios IDE en cada módulo involucrado en el desarrollo;
  • Usando el IDE, confirme los cambios en diferentes repositorios en una sola acción.
  • use el depurador para rastrear la ejecución del código de los módulos;

Despliegue a través del composer


Todo es familiar aquí. En el descriptor de implementación ( composer.json ) de la aplicación, especifique las direcciones de los repositorios con los módulos y prescriba las ramas maestras de los módulos como dependencias con la versión deseada:


 { "require": { "flancer64/habr-cvsn-mod-base": "dev-master as 0.1.0", "flancer64/habr-cvsn-mod-func": "dev-master as 0.1.0" }, "repositories": [ { "type": "vcs", "url": "https://github.com/flancer64/habr-cvsn-mod-base" }, { "type": "vcs", "url": "https://github.com/flancer64/habr-cvsn-mod-func" } ] } 

Después de ejecutar el comando:


 $ composer install 

./vendor con módulos aparecen en el directorio ./vendor , que a su vez contienen directorios .git :


  • ./vendor/
    • ./flancer64/
      • ./habr-cvsn-mod-base/
        • ./.git/
      • ./habr-cvsn-mod-base/
        • ./.git/

Es decir, el composer despliega inmediatamente las dependencias en una forma adecuada para el desarrollo (control de versiones). Solo queda configurar el IDE de PhpStorm (poner los módulos dependientes bajo control de versión):


imagen


y puede realizar un seguimiento de los cambios en todos los módulos desarrollados:


imagen


y confirmar todos los cambios en los repositorios locales al mismo tiempo:


imagen


y empujar al control remoto:


imagen


La depuración tampoco es un problema. Podemos establecer puntos de interrupción en cualquier línea del código del módulo base: después de iniciar la aplicación bajo el depurador, la interrupción ocurre cuando es necesario:


imagen


En general, el ambiente habitual, cómodo como zapatillas.


Despliegue normal a través de npm


A diferencia del composer npm no supone que en el proyecto ningún módulo del directorio node_modules pueda estar bajo control de versión. Podemos especificar en el descriptor de implementación package.json que el módulo debe cargarse desde un repositorio externo (por ejemplo, desde githib):


 { "dependencies": { "habr-cvsn-mod-base": "github:flancer64/habr-cvsn-mod-base", "habr-cvsn-mod-func": "github:flancer64/habr-cvsn-mod-func" } } 

pero no tenemos la opción de que npm cree un repositorio local para el módulo cargado (subdirectorio .git ).


Después de ejecutar el comando:


 $ npm install 

las dependencias se descargan e instalan localmente sin la posibilidad de utilizar el control de versiones:


imagen


(falta el subdirectorio ./.git/ en ./node_modules/habr-cvsn-mod-base/ )


Pero el depurador se detiene en el módulo base sin problemas:


imagen


Implementar a través de npm usando la opción de enlace


Para que los módulos de ./node_modules/ puedan mantenerse bajo control de versión, los desarrolladores de npm sugieren usar la opción ' link '. En resumen, la esencia del enfoque es que los módulos que necesitan ser versionados se clonan en una ubicación arbitraria en el disco del desarrollador (por ejemplo, en /home/alex/work/habr/ ), y luego se vinculan a /usr/lib/node_modules/ usando el comando:


 # npm link 

(Necesitaba privilegios de root para ejecutar)


Después de lo cual puede usar los siguientes comandos en el proyecto:


 $ npm link habr-cvsn-mod-base $ npm link habr-cvsn-mod-func 

npm encontrará los módulos apropiados en /usr/lib/node_modules/ y cerrará los subdirectorios correspondientes del proyecto ./node_modules/ :


 $ ls -lh ./node_modules/ total 0 lrwxrwxrwx 1 alex alex 57 jūl 2 16:18 habr-cvsn-mod-base -> ../../../../../../usr/lib/node_modules/habr-cvsn-mod-base lrwxrwxrwx 1 alex alex 57 jūl 2 16:18 habr-cvsn-mod-func -> ../../../../../../usr/lib/node_modules/habr-cvsn-mod-func 

Los módulos en /usr/lib/node_modules/ ellos mismos, a su vez, son enlaces a la ubicación original de los módulos:


 $ ls -lh /usr/lib/node_modules/ ... lrwxrwxrwx 1 root root 39 jūl 2 16:18 habr-cvsn-mod-base -> /home/alex/work/habr/habr-cvsn-mod-base lrwxrwxrwx 1 root root 39 jūl 2 16:18 habr-cvsn-mod-func -> /home/alex/work/habr/habr-cvsn-mod-func ... 

Y en su lugar permanente, el "registro" contiene un repositorio local:


 $ ls -lha /home/alex/work/habr/habr-cvsn-mod-base ... drwxrwxr-x 8 alex alex 4,0K jūl 2 16:18 .git ... 

Por lo tanto, podemos configurar el IDE para controlar los cambios en las dependencias del proyecto:


imagen


Los problemas comienzan cuando intenta ejecutar la aplicación:


 $ nodejs index.js internal/modules/cjs/loader.js:670 throw err; ^ Error: Cannot find module 'habr-cvsn-mod-base' at Function.Module._resolveFilename (internal/modules/cjs/loader.js:668:15) at Function.Module._load (internal/modules/cjs/loader.js:591:27) at Module.require (internal/modules/cjs/loader.js:723:19) at require (internal/modules/cjs/helpers.js:14:16) at Object.<anonymous> (/home/alex/work/habr/habr-cvsn-mod-func/src/index.js:3:14) ... 

La aplicación ve el módulo funcional vinculado, pero el módulo funcional en sí no ve el módulo básico vinculado. Para salir de la situación, use la tecla --preserve-symlinks para nodejs :


 $ nodejs --preserve-symlinks index.js 

Agregue la clave al comando de inicio del proyecto en el IDE:


imagen


Ahora el lanzamiento pasa, pero hay problemas con la depuración: los puntos de interrupción en las dependencias no funcionan. Puede detenerse en el módulo principal y seguir los pasos hacia las fuentes de dependencia, pero el IDE PhpStorm no ve el punto de interrupción en tiempo de ejecución, aunque muestra:


imagen


Los desarrolladores de IDE dicen que debería funcionar, pero no funciona (el caché se vació, el IDE se reinició).


En general, el propósito de esta publicación fue entrevistar a js-colegas cómo salen en una situación similar, pero en el proceso de redacción del artículo surgió otra combinación para el desarrollo del proyecto:


Colocación de códigos fuente en directorios internos de npm-project


Resultó que si para vincular usa clones de módulos de github creados por el composer en el subdirectorio ./vendor/ , en lugar de estar vinculado a directorios externos al proyecto, entonces los scripts js se ejecutan sin la --preserve-symlinks y, Más importante para mí, el IDE de PhpStorm ve puntos de interrupción dentro de los módulos. Porque no tiene sentido usar composer solo para clonar módulos de proyecto, utilicé el git habitual y cloné el código fuente de los módulos en el subdirectorio ./own_modules . Luego repitió las manipulaciones del párrafo anterior:


  • enlazó los módulos en el subdirectorio ./own_modules/... con la biblioteca del sistema /usr/lib/node_modules/ ;
  • módulos conectados en la biblioteca del sistema con el proyecto;
  • Configurado el IDE de PhpStorm para trabajar con repositorios locales en el subdirectorio ./own_modules/ ;

imagen


No sé cuál es la razón, pero cuando las fuentes de los módulos dependientes están dentro del proyecto, el resultado final del ensamblaje es significativamente diferente de cuando las fuentes de los módulos dependientes están en un directorio externo al proyecto.


Resumen


Comparando los dos enfoques para construir aplicaciones de módulos múltiples (PHP con composer y JS con npm ), puedo concluir que el composer más amigable para los desarrolladores que npm . Es posible que los desarrolladores del composer (primer lanzamiento en 2012) npm tenido en cuenta la experiencia de los desarrolladores de npm (primer lanzamiento en 2010). Sin embargo, con un esfuerzo adicional, npm también brinda la oportunidad de desarrollar aplicaciones de módulos múltiples en condiciones bastante cómodas.


Guiones de comandos para la implementación de proyectos en varios modos:


Source: https://habr.com/ru/post/458018/


All Articles