Pasar al contenido principal

Drupal y Composer 2

Composer 2.0 fue lanzado hace 4 meses. No quiero repetir las mejoras anunciadas en el artículo del lanzamiento (si no las conoces échales un ojo, son realmente interesantes), pero una destaca entre todas: el rendimiento.

Image
Composer 2.0 Speed Improvements: Time for initial update + install (bootstrapped project, empty cache) shows roughly 60% less time used by Composer 2

Source: blog.packagist.com by Jordi Boggiano

Bueno, probablemente esta gráfica haya captado tu atención y ya te planteas empezar a usar Composer 2.0., si es que no lo has hecho ya. Pero las actualizaciones de software nunca son fáciles, siempre hay algún dolor esperando taimadamente para saltar sobre ti cuando menos lo esperes. Aunque esto es cierto en muchas ocasiones, parece que esta vez no es así. Como se indica en el anuncio del lanzamiento, Composer 2.0 sigue siendo compatible con PHP 5.3 o superior, igual que  Composer 1, por lo que no debería haber problemas con la versión de PHP. Magnifico. Los archivos composer.lock son interoperables entre ambas versiones, lo que significa que puedes usar el mismo composer.json con Composer 1 y Composer 2. Puedes probar Composer 2 y si algo va mal no tienes más que revertir Composer a la versión 1: el fichero composer.json no se verá afectado durante el proceso. ¿Y qué pasa con la nueva sintaxis? ¿Hay comandos nuevos o comandos eliminados? Buena pregunta, pero no te preocupes: la mayoría de los comandos y argumentos son exactamente los mismos.

Para una descripción detallada de todos los cambios de Composer 2 recomiendo este artículo de PHP.Watch: "Composer 2: What's new and changed".

¿Y cómo empezar a usar Composer 2? Depende de cómo lo hayas instalado, pero si el ejecutable de Composer está bajo tu control (es decir, tienes los permisos necesarios para modificarlo) solo tienes que ejecutar:

composer selfupdate --2

Composer se sustituirá a sí mismo con la nueva y flamante versión 2.

Una vez hecho esto ya puedes probar Composer 2 en alguno de tus proyectos:

composer update --dry-run

¿Va todo bien? ¡Maravilloso! Continúa usando Composer 2. ¿Algo ha salido mal? Revierte Composer a la versión1:

composer selfupdate --1

Para hacer honor a la verdad, sí hay un punto en el que pueden surgir problemas: los plugins de Composer. Debido a que Composer ha cambiado un poco internamente, los plugins anteriores pueden fallar cuando se utilizan con Composer 2. Por suerte, el tiempo ha pasado y muchos plugins se han actualizado para funcionar con Composer 2.

Drupal y Composer 2

Drupal encaja a la perfección con Composer. Y la Comunidad Drupal está encantada con Composer. Es por eso que unas cuantas hábiles personas han estado trabajando para asegurar que Drupal funciona sin problemas con Composer 2.  La tarea principal consistía en actualizar los plugins de Composer requeridos por Drupal para que funcionasen con Composer 2. Estos cambios se completaron antes incluso de que Composer 2 fuera lanzado oficialmente (el registro de cambios tiene una fecha de casi dos semanas antes del anuncio de la publicación de Composer 2).

Pero, ¿cuál es la experiencia real usando Composer 2 en proyectos de verdad? Pues bastante buena, ciertamente. Como he comentado antes, los plugins de Composer pueden ser un problema. Sin embargo, la Comunidad Drupal ya ofrece una página de documentación para la transición a Composer 2 donde se pueden ver todos los plugins que necesitan ser actualizados para trabajar con Composer 2, los que ya no son necesarios (como el plugin Prestissimo que anteriormente era esencial) y los que aún necesitan cambios para ser compatible con Composer 2. Respecto al entorno de desarrollo, nosotros utilizamos un boilerplate propio que proporciona un sitio Drupal completo con un montón de extras: contenedores de Docker listos para ejecutar Drupal (gracias a Docker4Drupal), MkDocs para documentar el proyecto, Behat listo para lanzar sus tests, comprobación automática de código y algunas otras cosas. Y el caso es que Docker4Drupal ya proporciona imágenes con Composer 2, así que solo tuvimos que actualizar las imágenes de los contenedores y listo. ¡Fácil!

Composer 2 también ofrece un comando para comprobar los requerimientos del entorno que también comprueba los plugins:

composer check-platform-reqs

Además, es interesante destacar un cambio en cómo Composer 2 trata los repositorios. Con Composer v2  los paquetes se buscan en todos los repositorios en el orden en que los encuentra en el archivo composer.json. Si encuentra un paquete en un repositorio deja de buscar ese paquete en el resto de repositorios. Esto es ligeramente diferente de cómo se comporta Composer 1 y puede producir resultados algo diferentes. Si este es tu caso solo tienes que revisar la propiedad repositories en el archivo composer.json comprobando el orden en el que se declaran los repositorios.

Por cierto, Composer 1 y 2 siempre han sido muy seguros en el manejo de los repositorios. Hace un mes, el artículo "Dependency Confusion: How I Hacked Into Apple, Microsoft and Dozens of Other Companies" de Alex Birsan explicaba cómo utilizó los gestores de paquetes como npm (Javascript), pip (Python) y gems (Ruby) para instalar código malicioso en esas empresas. Es bastante interesante, si no lo has leído es una buena recomendación. ¿Y qué pasa con Composer? No está afectado, como bien explica Nils Adermann en este artículo: "Preventing Dependency Confusion in PHP with Composer".

Algunas notas sobre el rendimiento

Hagamos algunas pruebas simplistas. He recopilado la lista de los módulos más instalados de Drupal según Drupal.org. La primera prueba consiste en crear un proyecto de Drupal y requerir esos 100 módulos

Los comandos son los mismos para ambas versiones de Composer:

composer create-project drupal/recommended-project test-site
cd test-site
composer config minimum-stability dev
composer clear-cache
composer requiere --profile drupal/token drupal/ctools drupal/admin_toolbar drupal/pathauto drupal/metatag drupal/entity_reference_revisions drupal/redirect drupal/paragraphs drupal/field_group drupal/simple_sitemap drupal/inline_entity_form drupal/entity_browser drupal/search_api drupal/twig_tweak drupal/mailsystem drupal/config_filter drupal/address drupal/entity drupal/embed drupal/crop drupal/video_embed_field drupal/imce drupal/views_infinite_scroll drupal/google_analytics drupal/webform drupal/jquery_ui drupal/editor_advanced_link drupal/better_exposed_filters drupal/dropzonejs drupal/config_update drupal/eu_cookie_compliance drupal/colorbox drupal/block_class drupal/diff drupal/entity_embed drupal/extlink drupal/focal_point drupal/xmlsitemap drupal/ds drupal/views_bulk_operations drupal/easy_breadcrumb drupal/adminimal_admin_toolbar drupal/scheduler drupal/menu_link_attributes drupal/blazy drupal/smtp drupal/link_attributes drupal/config_split:^2.0 drupal/migrate_tools drupal/menu_block drupal/fontawesome drupal/svg_image drupal/swiftmailer drupal/smart_trim drupal/page_manager drupal/rabbit_hole drupal/key drupal/allowed_formats drupal/profile drupal/devel drupal/block_field drupal/robotstxt drupal/facets drupal/file_mdm drupal/password_policy drupal/autologout drupal/color_field drupal/memcache drupal/acquia_connector drupal/recaptcha drupal/restui drupal/anchor_link drupal/token_filter drupal/geofield drupal/views_bootstrap drupal/linkit:^6.0.0 drupal/views_data_export drupal/real_aes drupal/viewsreference drupal/entity_clone drupal/jquery_ui_datepicker drupal/username_enumeration_prevention drupal/encrypt drupal/contact_storage drupal/file_browser drupal/panels drupal/csp drupal/commerce drupal/feeds drupal/chosen drupal/default_content drupal/conditional_fields drupal/image_widget_crop drupal/entity_usage drupal/views_slideshow drupal/redis drupal/advagg

Como puede verse, he establecido "dev" como estabilidad mínima aceptada y he añadido una restricción de versión para los módulos LinkIt y Config Split. Si no se hacen obtendríamos un problema de dependencias. En cualquier caso es lo mismo para las dos versiones de Composer, ambas usarán el mismo conjunto de reglas, por lo que no debería afectar a la prueba. Adicionalmente, la caché de Composer se vacía para asegurarse de que no hay un aumento de velocidad debido a los datos en caché.

Los resultados

El primer paso es descargar Drupal usando Composer:

Image
Composer 1: Memory peak usage: 209MiB, time: 62.62s. Composer 2: Memory peak usage: 14.56MiB, time: 5.7s

 

El segundo paso, el más costoso, es requerir los 100 módulos más instalados:

Image
Composer 1: Memory peak usage: 1953.9MiB, time: 128.01s. Composer 2: Memory peak usage: 37.95MiB, time: 16.94s

¡Impresionante! En ambos casos, Composer 2 es unas 10 veces más rápido que Composer 1, y el consumo de memoria se reduce drásticamente. Sí, instalar 100 módulos de una sola vez no es algo que haces todos los días, pero cuando lo necesites te alegrarás de necesitar solo 40 MB en lugar de casi 2 Gigabytes de memoria disponible.

Se puede objetar que una única prueba no es suficiente y yo estaría de acuerdo, pero viendo la enorme diferencia creo que no hace falta saber el porcentaje exacto de brutal mejora que ofrece Composer 2.

Más resultados

Digamos que no vamos a utilizar Redis, así que vamos a eliminar el módulo correspondiente:

composer clear-cache
composer remove --profile drupal/redis
Image
Composer 1: Memory peak usage: 1751.8MiB, time: 49.29s. Composer 2: Memory peak usage: 18.88MiB, time: 0.13s

Composer 2 necesita 100 veces menos memoria y es casi 400 veces más rápido que Composer 1 al eliminar el paquete Redis. En este punto, creo que no hay necesidad de más pruebas: Composer 2 es increíblemente mejor haciendo su trabajo que Composer 1.

Un ejemplo real

Tenemos otra prueba muy convincente, en este caso de un ejemplo de uso en nuestro día a día. Mantenemos muchos proyectos diferentes, lo que significa que debemos asegurarnos de tener un buen número de sitios Drupal actualizados. Comprobar manualmente todos estos sitios no es una opción viable, así que tenemos un bonito job de Jenkins que comprueba afanosamente los proyectos mientras nosotros dormimos plácidamente: mientras nosotros nos centramos en las cosas que importan, el servidor Jenkins lo pasa en grande moviendo y testeando millones de bits de un lado a otro. Un buen trato, diría yo. El job primero detecta todas las actualizaciones disponibles mediante Composer,  pasando a procesar cada actualización una a una: actualiza, la comitea y pasa a la siguiente (esto nos permite revertir fácilmente una actualización concreta dejando el resto sin tocar). Una vez hecho esto, ejecuta la batería de pruebas del proyecto. A la mañana siguiente Jenkins nos informa de si podemos actualizar con seguridad o debemos revisar manualmente el proyecto. Esto es genial, pero desafortunadamente la ejecución del job era muy lenta debido a todas las operaciones realizadas con Composer. Hasta que llegó Composer 2:

Image
Graph showing the time needed to complete updates. At some point Composer 2 is used and time drops from 70 minutes to 5 minutes

Este gráfico muestra el tiempo que necesita el trabajo para completar todas las tareas. ¿Ves cuándo usamos Composer 2 en ese proyecto? Apuesto a que no necesito agregar una flecha roja que lo apunte.

Este gráfico muestra el tiempo que necesita el job para completarse. ¿Ves en qué momento empezamos a utilizar Composer 2? Estoy seguro de que no hace falta que añada una flecha roja señalando el punto exacto.

Conclusión

Es muy fácil: empieza a usar Composer 2 tan pronto como te sea posible. Composer 1 es extremadamente lento, esto es así, mientras que Composer 2 es extremadamente rápido. 

Image
Two guys are playing with swords in the office, when someone tells them to back to work they say as excuse that they are waiting for Composer. The complaining voice now says: "Oh, Carry on"

Empieza a usar Composer 2 y haz que esta viñeta sea obsoleta; a menos que aún quieras tener una excusa para la pausa del café, claro.

Corolario

El síndrome del impostor es algo que se da bastante, tanto en la Comunidad Drupal como en muchas otras comunidades. Nadie es perfecto y es fácil ver nuestros propios errores y pensar que no somos lo suficientemente buenos. Pero no me quiero centrar en esto porque ya hay un montón de excelentes charlas y artículos sobre este tema. Solo quiero señalar una cosa: Composer 1 es un buen software y cambió el mundo de PHP mediante su gestión de dependencias. Sin embargo, viendo la increíble mejora de la versión 2, ¿no crees que podría haber sido mucho mejor en primer lugar? Claro que sí, pero incluso con esos defectos, era un gran software y merecía la pena. Recuerda esto cuando te juzgues a ti mismo y a tu trabajo con excesiva dureza.

Image
RIcardo Sanz Ante

Ricardo Sanz

CTO