0xf41f800000 for PSP TMR

Directus: Qué es y Cuáles son sus Ventajas frente a un Backend Personalizado

Públicado el

14 de febrero de 2024

a las

17:15

Directus es una potente herramienta para crear y gestionar grandes cantidades de datos de forma fácil e intuitiva. La principal característica de un headless CMS, en este caso, Directus, es que te permite presentar tus datos de la forma que más creas conveniente para tu web o aplicación. Esto y otros aspectos más es de lo que os voy hablar hoy.

Actualizado el

21 de noviembre de 2024

a las

18:22

Seguramente ya sabéis qué es un headless CMS y cuáles son sus principales características, si no, os lo explico brevemente. Un headless CMS es una potente herramienta que te permite crear y gestionar grandes cantidades de datos, datos que más tarde puedes decidir cómo presentar de forma independiente.  Esta característica de poder elegir cómo presentar tu contenido es lo que diferencia un CMS convencional de un headless CMS.

En esta ocasión vamos a explorar Directus, un headless CMS bastante flexible que puede ayudar a acelerar en gran medida vuestro proceso de desarrollo.

Qué es Directus

Directus es un headless CMS de código abierto desarrollado por Ben Haynes en 2004. El proyecto ha evolucionado de forma constante gracias a la colaboración de cientos de desarrolladores y el propio equipo de Directus. 

Su naturaleza de código abierto y la posibilidad de que casi cualquier persona pueda colaborar hacen de Directus una plataforma robusta. Ofrece una extensa lista de características útiles para desarrollar sitios web o bien aplicaciones de manera rápida y efectiva. 

Además de las características estándar de cualquier otro headless CMS, puedes consumir su API a través de dos enfoques distintos: GraphQL y REST.  Aunque no es necesario realizar configuraciones adicionales para consumir la API a través de REST o GraqhQL, es importante tener en cuenta que el acceso público a las colecciones está restringido por defecto. Sin embargo, puedes generar un token con tu usuario administrador para acceder a estos datos o configurar permisos públicos en las colecciones de tu instancia de Directus.

Características destacadas

Para comenzar a explorar la extensa lista de funcionalidades que ofrece Directus vamos hablar sobre las más destacadas y en especial de una que me parece de lo más interesante: los Flows.

¿Qué son los Flows? Los Flows son la forma que ofrece Directus para automatizar tareas y procesar información a través de eventos y existen varios tipos, veamos algunos de ellos.

Event Hooks

Los Event Hooks son eventos que se activan con una interacción en tu instancia de Directus o con modificaciones en los datos de tus colecciones. Puedes configurar dos tipos: los bloqueantes, que detienen temporalmente otras acciones hasta que se complete el Event Hook, y los no bloqueantes, ideales para ampliar las funcionalidades de Directus, como eliminar elementos residuales de relaciones M2A.

Además, puedes ajustar el Scope del Event Hook (acción que lo desencadena), como crear, actualizar o eliminar elementos. Para más detalles, te invito a explorar la Documentación oficial.

Webhooks

Los Webhooks son una técnica para la comunicación en tiempo real entre aplicaciones, ideal para la automatización basada en eventos. Son esenciales en escenarios donde necesitas conocer el estado de una transacción en tiempo real, como el seguimiento del estado de una compra utilizando Stripe.

Schedule (CRON)

Los Schedule (CRON) son demonios que se ejecutan a intervalos regulares, similares a los programadores de tareas en sistemas *nix o Windows. Son útiles para ejecutar tareas de forma programada y regular.

Another Flow

Esta técnica implica desencadenar un Flow a través de otro. Es útil, por ejemplo, cuando un Event Hook falla en la eliminación de elementos relacionados a través de M2A, permitiendo el registro del fallo y la activación de otro Flow para notificar a los desarrolladores, o por lo menos ese es el uso que les daría yo.

Manual

Este tipo de Flow se inicia manualmente desde la colección correspondiente, ideal para crear botones integrados para reportar fallos de forma sencilla y directa.

Ahora que sabemos qué son los Flows nos podemos centrar en otro aspecto interesante de Directus: su interfaz de usuario fácil e intuitiva.

Como desarrollador es fácil olvidar que una herramienta es solo eso, una herramienta. Es importante tener en cuenta en todo momento que, nuestro objetivo principal es ofrecer la mejor experiencia de usuario posible. 

Directus cuenta con una interfaz de usuario flexible, es posible mostrar directorios solo a ciertos usuarios con roles específicos, de la misma forma se pueden ocultar colecciones a los usuarios con un rol de editor de contenido, también es posible limitar las acciones que los usuarios con distintos roles pueden ejecutar.

Dichas acciones van desde lo más básico cómo eventos CRUD hasta acciones más complejas como la creación de nuevas colecciones, Flows o incluso nuevos roles y permisos.

Hay que destacar que cada usuario puede personalizar su interfaz según su gusto e idioma de preferencia. Función que a mi parecer es muy atractiva.

Otra característica de Directus es la posibilidad de importar y exportar  la información de tus colecciones en diferentes formatos como JSON, CSV, XML o YAML, además puedes aplicar distintos filtros como, el máximo de registros a exportar, filtrado por campos como publicaciones por autor,  de forma ascendente o descendente o incluso por palabras clave.

Mayor velocidad de desarrollo

Desarrollar un backend personalizado consume tiempo y recursos, por eso utilizar un headless CMS, como Directus, u otro que satisfaga tus necesidades, puede ser una solución rápida y económica. Veamos por qué.

Dependiendo de los requisitos de nuestra aplicación o sitio web, una solución personalizada implica desarrollar una interfaz de usuario para gestionar los distintos roles y acciones. Para permitir que los administradores de nuestra web puedan crear nuevos roles y gestionar los existentes, debemos manejar las relaciones de las tablas en nuestra base de datos, así como endpoints y además realizar pruebas exhaustivas para garantizar no solo el correcto funcionamiento de nuestro sistema, sino también su seguridad. Todo lo anterior es posible, pero tiene un precio: tiempo y recursos. Dos cosas que no siempre coinciden.

Una de las ventajas de utilizar un headless CMS como Directus, que además es de código abierto, es que ha sido puesto a prueba por miles de usuarios y desarrolladores en distintos escenarios. Utilizar un sistema respaldado por otros desarrolladores que quizá tengan mucha más experiencia en otros campos en los que tú no te especializas genera cierta confianza y tranquilidad.

Incluso aún implementando un headless CMS, es posible escalar nuestra aplicación extendiendo las funcionalidades a través de microservicios. 

Facilidad de implementación

Otro aspecto que se puede considerar una ventaja frente a un backend personalizado es la facilidad de implementación. Dependiendo de tu experiencia previa con Directus y de la complejidad de los requisitos de tu aplicación, es posible tener una instancia up and running con bastantes colecciones y relaciones en un día. 

Esto se debe a que, como mencioné anteriormente, Directus te permite consumir tus datos a través de REST o GraphQL, modelar tus datos a través de una interfaz gráfica intuitiva, crear relaciones complejas en cuestión de minutos y gestionar los permisos con la misma facilidad.

Sistema de gestión de usuarios y roles integrado

Gracias a la gestión modular de roles de usuario, es posible reducir el riesgo de que un usuario se cargue información crítica del sistema. Esto hace que para utilizar Directus no sea necesario tener un conocimiento avanzado de herramientas de gestión de contenidos. Cualquier usuario que haya trabajado anteriormente con un sistema de este tipo es capaz de utilizarlo para crear, actualizar o eliminar contenido.

Directus te permite configurar cuantos roles y configuraciones necesites en tu instancia.

Opciones disponibles para desplegar una nueva instancia de Directus.

Directus Cloud es una de las 3 formas que ofrece Directus para implementar tu propia instancia. Este método, al ser de pago, cuenta con las garantías de un equipo técnico especializado y, en caso de que algo vaya mal, tendrás soporte técnico 24/7. Directus Cloud cuenta con actualizaciones periódicas de forma automática, lo que se traduce en un software siempre actualizado y con la última versión.

¿Merece la pena la Directus Cloud? Depende del contexto. En mi caso personal utilizo la versión self-hosted, es decir, me encargo de gestionar mi propia instancia y asegurarme de que siempre esté actualizada en su última versión.

Self-Hosting es otra de las opciones disponibles para desplegar tu propia instancia, la utilizo en mi portfolio y se ejecuta a través de una imagen de Docker. Es la forma más económica para desplegar Directus y te permite un control a un nivel más granular. Una de las desventajas que tiene la versión self-hosted es que no cuentas con un equipo técnico para darte soporte. Sin embargo, en caso de ser desarrollador, esto no tiene mayor importancia si no necesitas asistencia, ya que con la documentación disponible o incluso con los issues abiertos en GitHub es suficiente para resolver cualquier incidencia. 

Complejidad de las consultas a la API

La consulta a la API generada por Directus podría considerarse como ambas: una ventaja y una desventaja. Veamos por qué es una ventaja y cuando podría convertirse en lo contrario.

Cuando creas una colección en Directus puedes acceder a ella, siempre y cuando, tengas los permisos adecuados, a través de REST o GraphQL. Ambas formas de consumir el API pueden resultar relativamente sencillo dependiendo de con qué enfoque te sientas más cómodo, no tener que configurar ningún endpoint ni tampoco tener que ajustar los permisos de acceso son un punto a favor, puesto que, para hacer una consulta tan solo necesitas generar un token de acceso desde el panel de usuario con el que estés accediendo, el token generado te dará acceso a todas las colecciones a las que tengas permiso para acceder, modificar o eliminar, bastante straight forward y sin complicaciones.

Pero si lo anterior es todo ventajas... ¿Qué podría ser tan negativo de todo esto? Esa misma flexibilidad para crear tus datos y acceder a ellos. Hay que tener en cuenta que no todas las aplicaciones tienen como requisito un simple crud con relaciones sencillas. En ocasiones las relaciones pueden ser bastante complejas, en especial las M2A, este tipo de relaciones se basa en relacionar un campo de tu colección con otra que a su vez puede estar relacionada con otra colección, y así podemos seguir dependiendo de lo que estemos construyendo, para hacer este tipo de escenario más fácil de entender, veamos un breve ejemplo. 

Una consulta básica a, por ejemplo, esta publicación, tendría la siguiente estructura: 

typescript
http://localhost:8055/items/posts?fields=*,filter[translations][slug][_eq]=directus-que-es-y-cuales-son-sus-ventajas-frente-a-un-backend-personalizado

Dependiendo de la estructura de nuestra colección, la respuesta de la consulta anterior se vería similar a este JSON:

json
{
    "data": [
        {
            "date_created": "2024-07-04T15:15:24.000Z",
            "date_updated": "2024-07-09T09:10:30.000Z",
            "cover": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "user_created": "xxx-xxxxx-xxx-xxx-xx",
            "translations": [
                929
            ],
            "content": [
                3913,
                3915,
                3916
            ]
        }
    ]
}

La respuesta contiene campos de tipo Array numérico, sin embargo no podemos acceder a los valores de esos campos sin antes extender un poco más la profundidad de nuestra consulta 

typescript
http://localhost:8055/items/posts?fields=*,translations.*,content.*&filter[translations][slug][_eq]=directus-que-es-y-cuales-son-sus-ventajas-frente-a-un-backend-personalizado
json
{
    "data": [
        {
            "date_created": "2024-07-04T15:15:24.000Z",
            "date_updated": "2024-07-09T09:28:27.000Z",
            "cover": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "user_created": "xxx-xxxxx-xxx-xxx-xx",
            "translations": [
                {
                    "id": 929,
                    "posts_id": "x",
                    "languages_code": "es",
                    "title": "Directus: Qué es y Cuáles son sus Ventajas frente a un Backend Personalizado",
                    "slug": "directus-que-es-y-cuales-son-sus-ventajas-frente-a-un-backend-personalizado",
                    "summary": "<p>Directus. Una potente herramienta para crear y gestionar grandes cantidades de datos de forma f&aacute;cil e intuitiva. La principal caracter&iacute;stica de un headless CMS, en este caso, Directus, es que te permite presentar tus datos de la forma que m&aacute;s creas conveniente para tu web o aplicaci&oacute;n. Esto y otros aspectos m&aacute;s es de lo que os voy hablar hoy.</p>",
                    "author_pick": false,
                    "meta_description": null,
                    "status": "published"
                }
            ],
            "content": [
                {
                    "id": 3913,
                    "posts_id": "x",
                    "item": "x",
                    "collection": "table_of_contents",
                    "sort": "x"
                },
                {
                    "id": 3915,
                    "posts_id": "x",
                    "item": "x",
                    "collection": "title",
                    "sort": "x"
                },
                {
                    "id": 3916,
                    "posts_id": "x",
                    "item": "x",
                    "collection": "wysiwyg",
                    "sort": "x"
                }
            ]
        }
    ]
}

Aunque hemos extendido la profundidad de nuestra consulta, seguimos sin poder acceder a todos los campos de las relaciones M2A. Esto se debe a que ahora tenemos que extender la profundidad apuntando a las colecciones de cada una de las relaciones M2A, eso si queremos acceder a una, algunas o todas. Veamos, por ejemplo, el contenido de la relación con los WYSIWYGS.

json
http://localhost:8055/items/posts?fields=*,translations.*,content.*, content.item.*, content.item.translations.*&filter[translations][slug][_eq]=directus-que-es-y-cuales-son-sus-ventajas-frente-a-un-backend-personalizado
json
{
    "data": [
        {
            "date_created": "2024-07-04T15:15:24.000Z",
            "date_updated": "2024-07-09T09:28:27.000Z",
            "cover": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "user_created": "xxx-xxxxx-xxx-xxx-xx",
            "translations": [
                {
                    "id": 929,
                    "posts_id": "x",
                    "languages_code": "es",
                    "title": "Directus: Qué es y Cuáles son sus Ventajas frente a un Backend Personalizado",
                    "slug": "directus-que-es-y-cuales-son-sus-ventajas-frente-a-un-backend-personalizado",
                    "summary": "<p>Directus. Una potente herramienta para crear y gestionar grandes cantidades de datos de forma f&aacute;cil e intuitiva. La principal caracter&iacute;stica de un headless CMS, en este caso, Directus, es que te permite presentar tus datos de la forma que m&aacute;s creas conveniente para tu web o aplicaci&oacute;n. Esto y otros aspectos m&aacute;s es de lo que os voy hablar hoy.</p>",
                    "author_pick": false,
                    "meta_description": null,
                    "status": "published"
                }
            ],
            "content": [
                {
                    "id": 3913,
                    "posts_id": "x",
                    "collection": "table_of_contents",
                    "sort": "x",
                    "item": {
                        "id": "x",
                        otros campos...
                        "content": [
                            753,
                            234,
                            249,
                            025,
                            786
                        ],
                        "translations": [
                            {
                                "id": "x",
                                "tables_of_contents_id": "x",
                                "languages_code": "es",
                                "title": "Tabla de contenidos"
                            }
                        ]
                    }
                },
                {
                    "id": 3915,
                    "posts_id": "x",
                    "collection": "title",
                    "sort": "x",
                    // otros campos...
                    "item": {
                        "translations": [
                            {
                                "id": "x",
                                "titles_id": "x",
                                "languages_code": "es",
                                "title": "Webhooks",
                                // otros campos...
                            }
                        ]
                    }
                },
                {
                    "id": 3916,
                    "posts_id": "x",
                    "collection": "wysiwygs",
                    "sort": "x",
                    "item": {
                        "id": "x",
                        "wysiwyg_code_name": "La consulta a la API generada por Directus podría considerarse como ambas:",
                        "text_align": null,
                        "max_width": "unset",
                        "margin_top": null,
                        "translations": [
                            {
                                "id": "x",
                                "wysiwygs_id": "x",
                                "languages_code": "es",
                                "wysiwyg": "<p>La consulta a la API generada por Directus podr&iacute;a considerarse como ambas: una ventaja y una desventaja. Veamos por qu&eacute; es una ventaja y cuando podr&iacute;a convertirse en lo contrario.</p>\n<p>Cuando creas una colecci&oacute;n en <strong>Directus&nbsp;</strong>puedes acceder a ella, siempre y cuando, tengas los permisos adecuados, a trav&eacute;s de <strong>REST</strong> o <strong>GraphQL. </strong>Ambas formas de consumir el API pueden resultar relativamente sencillo dependiendo de con qu&eacute; enfoque te sientas m&aacute;s c&oacute;modo, no tener que configurar ning&uacute;n endpoint ni tampoco tener que ajustar los permisos de acceso son un punto a favor, puesto que, para hacer una consulta tan solo necesitas generar un token de acceso desde el panel de usuario con el que est&eacute;s accediendo, el token generado te dar&aacute; acceso a todas las colecciones a las que tengas permiso para acceder, modificar o eliminar, bastante straight forward y sin complicaciones.</p>\n<p>Pero si lo anterior es todo ventajas... &iquest;Qu&eacute; podr&iacute;a ser tan negativo de todo esto? Esa misma flexibilidad para crear tus datos y acceder a ellos. Hay que tener en cuenta que no todas las aplicaciones tienen como requisito un simple crud con relaciones sencillas. En ocasiones las relaciones pueden ser bastante complejas, en especial las <strong>M2A</strong>, este tipo de relaciones se basa en relacionar un campo de tu colecci&oacute;n con otra que a su vez puede estar relacionada con otra colecci&oacute;n, y as&iacute; podemos seguir dependiendo de lo que estemos construyendo, para hacer este tipo de escenario m&aacute;s f&aacute;cil de entender, veamos un breve ejemplo.&nbsp;</p>\n<p>Una consulta b&aacute;sica a, por ejemplo, esta publicaci&oacute;n, tendr&iacute;a la siguiente estructura:&nbsp;</p>"
                            }
                        ]
                    }
                }
            ]
        }
    ]
}

La consulta anterior se puede simplificar accediendo a todos los campos, pero eso significa devolver un objeto enorme con mucha información que quizá no necesites. La consulta sigue siendo relativamente sencilla pero aún hay campos donde necesitamos seguir expandiendo la profundidad. Creo que esto es ejemplo suficiente sobre lo complejas que se pueden volver las consultas a Directus.

Sin embargo, hay que matizar lo anterior un poco, si se tiene en cuenta que muchas veces lo complejas que puedan llegar a ser las consultas dependen más del modelado de las colecciones que del estilo de consulta de Directus, puede que esto no sea un problema como tal si no más bien una cuestión de diseño de las colecciones. 

Soporte de la comunidad

Directus cuenta con una documentación que a veces puede llegar a ser escasa o poco detallada. Incluso complicada para un primer contacto con esta tecnología.

Sin embargo, Directus cuenta con una comunidad bastante activa en distintas plataformas: GitHub, Discord, Youtube y además cuentan con un blog donde publican todas las novedades y nuevas features de Directus.

La presencia en diversas plataformas hace que encontrar información sobre este headless CMS no sea una tarea difícil, la mayor parte de los issues se encuentran registrados en GitHub y puedes obtener una respuesta mucho más rápida a través de los distintos canales de su servidor de Discord.

Gracias a que la implementación de tipo self hosted está bastante extendida también cuentan con un canal de discord dedicado exclusivamente a ello.

Gestión de contenido residual en relaciones M2A

Aunque Directus permite la eliminación en cascada entre algunas relaciones, esto no funciona así con todo tipo de relación, como es el caso de las relaciones de tipo M2A.

Por ejemplo, imagina una colección llamada "posts" que contiene un campo relacional llamado "content" de tipo M2A. Este campo está relacionado con otras colecciones. Cuando eliminas el valor de "content", se elimina la relación entre tu elemento en la colección "posts" y, si está configurado para eliminación en cascada, también se eliminará de la colección intermedia que tu campo necesita para enlazar con el elemento en la colección original.

Sin embargo, surge un pequeño problema: lo que se elimina es la relación; el elemento original aún permanece en la colección a la que pertenece. Esto puede resultar en contenido residual que quizá no vas a utilizar más. 

¿En qué tipo de situaciones podría convertirse en contenido residual? Veamos. Si tu campo content dentro de la colección posts permite añadir títulos y WYSIWYGS, es probable que algún día alguien elimine una publicación o un elemento de tipo título o WYSIWYG.  En esas situaciones, Directus no gestiona la eliminación en cascada de dichos elementos, como ya mencioné anteriormente, se elimina la relación y en caso de estar configurada, también el elemento de la colección intermedia, pero nunca se elimina el elemento de su colección original.

¿Qué solución hay para este tipo de situaciones? Para eso están los Flows y los Microservicios. Al menos hasta que Directus lo soporte de forma nativa.  

La curva de aprendizaje

Antes de concluir este artículo, hablemos un poco sobre la curva de aprendizaje.

Desde el punto de vista de un editor de contenido, Directus puede ser bastante sencillo de aprender a utilizar, principalmente porque se da por sentado que el equipo o la persona a cargo de la implementación ha tenido en cuenta los distintos roles; administradores, desarrolladores, editores, editores invitados, o sean cuales sean los roles que tenga tu instancia. 

Por lo que, cada uno de los usuarios estará configurado según los permisos que tenga cada rol. Por ejemplo, un editor invitado solo puede ver y editar las publicaciones que él haya creado y un editor interno podrá cambiar el estado de su propia publicación, o de editores invitados, pero nunca de otros editores. Y solo el administrador podrá eliminar una publicación.

Esta jerarquía de roles hace que los usuarios poco técnicos tengan un curva de aprendizaje razonable, puesto que se van a ocupar solo de las responsabilidades que su rol tenga y nada más, no van a ver paneles de configuración de colecciones, ni publicaciones de otros editores o sea cual sea el caso, verán solo lo que necesitan ver.

Ahora bien, ¿qué hay de la curva de aprendizaje para los desarrolladores? Esto depende mucho del nivel de experiencia, tiempo, y recursos. En mi caso en particular la curva de aprendizaje fue regular, un poco abrumadora por momentos, pero teniendo en cuenta que fue en un entorno laboral y con prisas, estuvo bastante bien.

La primera vez que toqué Directus fue en mi trabajo, no había tiempo a pararse demasiado a ver cómo funciona ni las mejores prácticas o posibles cuellos de botella, pero contaba con compañeros con mucha más experiencia con Directus que yo, un buen ambiente de trabajo y un jefe flexible. Todo esto hizo que mi primer contacto fuera bastante positivo. Sin embargo, recomendaría ponerse a practicar y analizarlo en tiempos libres, eso facilita mucho el aprender cómo trabajar con Directus.

Conclusión final

Un headless CMS como Directus puede ser una gran alternativa a un backend personalizado para tus proyectos cuando el tiempo es escaso o cuando prefieres centrarte en el frontend más que en el backend.

En mi caso, disfruto mucho reinventando la rueda e investigando sobre cómo funcionan las cosas o cómo se hacen, pero he de admitir que esto no siempre es práctico, en especial cuando la prioridad está en los resultados rápidos y no tanto en la experiencia de un backend completamente personalizado, tema que espero tratar en el futuro.

Otro punto a favor de utilizar una herramienta como Directus es su interfaz gráfica que puede resultar fácil de usar para los usuarios finales, te ahorras tener que diseñar y maquetar un panel de administrador personalizado (con todo lo que esto conlleva).

De momento lo dejamos aquí y en otra publicación veremos cómo implementar una instancia básica de Directus self-hosted utilizando Docker en un servidor ubuntu.