Optimizar Pagespeed en Odoo
¿Es posible optimizar el Pagespeed en nuestro Odoo? ¿A qué nivel?
No es ningún misterio que Odoo es uno de los ERP más importantes y sonantes de la actualidad. Y tampoco será misterio para sus usuarios, desarrolladores y webmaster que las webs en Odoo no obtienen una puntuación "perfecta" en las plataformas referentes a la medición del Pagespeed. Pero, ¿es en verdad algo tan vital como parece? ¿es posible optimizar un sistema ERP como lo es Odoo? Averiguémoslo, dejando en claro algunos puntos.
¿Es necesaria una puntuación de 100/100 en Pagespeed?
No. Rotundo no. Si se utiliza el pagespeed como una herramienta de consejos para optimizar lugares de la web donde tenemos dudas (como las imágenes o la compresión de archivos) haremos un buen uso de ella. Pero sino, podemos asegurar que será algo de nunca acabar. Para el común de las herramientas, siempre se puede optimizar más. Siempre habrá una compresión JPG más eficiente, pero no siempre nos interesa que nuestras imágenes estén rotas. O el famoso "contenido JS y CSS que bloquea aspectos visibles". En herramientas como Odoo, que proveen de un CMS, no es posible cambiar eso (aún de serlo, se trataría de un trabajo para nada escalable, titánico y carísimo). ¿Y todo para qué? Para ahorrar milisegundos que no hacen la diferencia a los niveles de conectividad actual. Como los test de pagespeed son algo muy común de encontrar en la web (Google mismo provee de uno) un usuario de Odoo que no se encarga del desarrollo y solo se beneficia del ERP (un cliente, vamos) se preocupará mucho al ver una decena de mensajes de error o "necesidad de optimización" en colores rojos y anaranjados, con signos de advertencias y cruces. Lo cierto es que el cartel de error saldrá tanto si estamos cargando imágenes de enorme peso en forma desproporcionada (donde si es posible ahorrar mucho tiempo de carga), como si el caché de un archivo es mayor del promedio estimado (donde no se ahorra tiempo de carga en sí). Los criterios son muy poco prácticos para el desarrollador, pero le hacen ver a un usuario medio un problema donde no lo hay. Lo mejor es siempre probar estos test dos o tres veces a lo largo del día, sin realizar cambios en el código. Se sorprenderán de ver, en la mayoría de las ocaciones, calificaciones diametralmente opuestas (en especial en lo referido a compresión y uso el caché).
¡Estoy perdiendo potenciales visitantes! ¡Ayuda!
Quizás lo más complicado de todo el asunto del Pagespeed es explicarle a un cliente, quien con razón se preocupa de los informes de Google y otras herramientas, que sus miedos no lo son tanto. A menudo se recomienda Odoo a pequeñas y medianas empresas que busquen aumentar su competitividad, y todo funciona de maravilla. Pero al tiempo aquellos que utilizan Odoo se interiorizan con las herramientas de Pagespeed, como Google Pagespeed Insight, y obtienen reportes con carteles como por ejemplo "estás perdiendo el 20% de tus visitantes". ¿En qué se basa Google Pagepseed Insight para tal afirmación? En la velocidad de carga de tu website. No nos malinterpreten, mejorar la carga de un sitio web siempre es bueno. Pero si tu website tarda unos 3 segundos en cargar puedo asegurar que, en caso de perderse visitantes, la razón no es -ni cerca- la velocidad. El SEO no contempla la optimización o velocidad de carga (por más que nos hagan creer que si). Es preferible poner nuestros esfuerzos en posicionar mejor nuestro website que en intentar cumplir directivas imposibles que reduciran el tiempo de carga solo un 2%.
¿Cómo optimizar un Odoo?
Contrariamente a todo esto, y pese a que las versiones más actuales de Odoo están de por si bastante optimizadas, podemos llevar a cabo ciertas prácticas para mejorar, aún más si cabe, el rendimiento del Website y de Odoo. Es importante destacar que estos consejos no son solo para mejorar el tiempo de carga y rendimiento de un usuario visitante de nuestro Website, sino también de los usuarios que trabajan con el ERP de Odoo en cuestión:
Optimizar imágenes con mozjpeg y pngquant (Odoo va a guardarlas en la base de datos con otros sistemas de compresión, por lo que mucha veces no será necesario). No utilizar imágenes con una resolución altísima, mantenerse en los estándares actuales (especialmente si una mayor resolución no significa una mayor calidad).
Habilitar Gzip en el servidor. Para NGINX se puede usar el ngx_http_gzip_module y para Apache el mod_deflate. Recordar utilizarlo tanto en documentos de texto como en imágenes.
Utilizar una Red de Distribución de Contenidos como comentamos en otra entrada de nuestro blog, lo que aumenta de forma considerable la carga de assets estáticos.
Tener buen control de módulos de terceros. En muchos casos empleamos módulos genéricos que utilizan más recursos JavaScript y CSS de los que necesitamos. Por ejemplo, un módulo de mejora de nuestro Website puede incluir modificaciones al website_blog y al website_forum, lo que obligaría a nuestro Odoo a instalar módulos que no necesitamos. Sin contar que muchas veces tendremos código de JS y CSS que no se utiliza exactamente. Para esto es conveniente conocer todo el módulo antes de instalarlo. Lo mismo ocurre con código de prueba en proyectos muy grandes, donde el poco orden nos hace tener segmentos repetidos de CSS / JS o inutilizados. Existen herramientas que pueden ayudarnos a dicha labor, nosotros desarrollamos la css-deprecator-tool, que puede ayudarnos a identificar IDs y Clases que no existen en un HTML pero que se llaman en un CSS. Aún no es compatible con Odoo, pero está realizado en Python y no sería dificil portabilizarlo. A quien le interese, este es el repositorio: css-deprecator-tool.
Programar JavaScript de forma eficiente. Si se programa con JavaScript, y ese código crece lo suficiente, es un buen momento de considerar utilizar lo más reciente y estable de las versiones más recientes de ECMAScript (el auténtico lenguaje de JavaScript). Hoy día la inmensa mayoría de los navegadores soporta ECMAScript 6, y como versión es muy interesante ya que permite utilizar variables tipo let y const, las cuales funcionan mejor. Ocurre lo mismo al momento de recorrer Arrays enormes, existen diversas funciones para hacer lo mismo y algunas son más eficientes que otras. Dependerá mucho de la experiencia como desarrollador de JavaScript, pero hay que tener en cuenta que suelen presentarse formas optimizadas de programación en dicho lenguaje, un buen repaso a la documentación de las últimas versiones puede ayudar. Como dato extra, recordar que Odoo posee sus propias declaraciones en JavaScript, para permitir cargas asincrónicas, entre otras funcionalidades. Ver documentación en JavaScript de Odoo.
Limitar las redirecciones. Gracias a los Controllers de Odoo es muy sencillo realizar una redirección, y hay que tener cuidado en abusar de ellas. Sin darnos cuenta, podemos hacer muchas redirecciones al mismo link (especialmente en migraciones de otras plataformas), y cada una de ellas representa la carga parcial de la página de Odoo. Lo mejor es tener un buen control y criterio antes de realizar una. Eso no mejora el rendimiento per se, pero es una actitud a evitar para que la optimización no decaiga.
Revizar las solicitudes de PostgreSQL. Las bases de datos, en proyectos grandes, pueden ser un problema. En principio, deberiamos hacer un chequeo de la salud de nuestra base de datos. Pero no solo eso, también es importante entender sus usos para poder optimizar ciertos ciclos. No hay un consejo exacto, depende mucho del caso, pero es preferible tener una sólida experiencia en PostgreSQL (o tener alguien en el equipo que pueda darse a la tarea). A medida que crecen los registros, crecen las llamadas y, por muy optimizado que esté PostgreSQL, a la larga se va a empezar a sentir el problema. Lo ideal es tener un plan pensado para cada empresa. Hay casos donde un cliente, por desconocimiento, carga imágenes enormes de productos en su Odoo eCommerce, lo que a la larga termina afectando al rendimiento. Una solución puede ser preparar un script en Python que no permita guardar imágenes de un peso superior o de una resolución determinada (datos que pueden conseguirse simplemente con Odoo). Otro caso recurrente es la acumulación de registros viejos, especialmente de Presupuestos, Facturas y Proyectos. Nos referimos a grandes proyectos de Odoo, donde se generan decenas de presupuestos y facturas al día, y donde se emplea el módulo de Proyectos de forma constante entre los empleados. Normalmente las empresas suelen mostrarse firmes cuando la sugerencia es eliminar un presupuesto viejo (archivado hace años), y tiene su razón. Pero los Proyectos es una discusión más amena, y podemos llegar a armar un Script en Python que elimine registros del módulo de Proyectos que fueron archivados hace más de un año como una medida de optimización de la base de datos. Finalmente, hay varias maneras de optimizar la base de PostgreSQL en general, como explicamos en otra entrada.
Utilizar Campos indexados, pero con criterio. En Odoo los campos aceptan la posibilidad de ser indexados mediante la condición index=True, desde Python. Es interesante, puesto que le agrega un index al campo con lo cual puede ser localizado de forma altamente eficiente y velóz al hacer una consulta. Así es, tiene que ver con la base de datos. El problema es que los campos indexados aumentan, de forma considerable, el volumen de una base de datos muy rápidamente, lo cual es contraproducente también. ¿Lo ideal? Tener criterio a la hora de elegir que campos indexar y cuales no. Un consejo es detectar aquellos campos que se emplean de forma muy frecuente en las búsquedas, y eso depende del uso que le den los usuarios al Odoo.
Tener un servidor a medida. Cada Odoo es diferente, maneja una cantidad de usuarios muy variable y, por lo tanto, necesitamos un servidor a la medida de nuestro odoo. El cálculo para saber cuantos usuarios soportará nuestro server es el siguiente: (#CPU * 2) + 1. Es decir, el número de CPU multiplicado por dos más uno. Si tenemos 4 CPU, quiere decir que podremos albergar unos 9 usuarios (es un valor estimativo, depende mucho de las labores, pero ayuda a darnos una idea). Para esto Odoo distingue entre los Heavy Workers y los Light Workers. Según la documentación, Odoo considera que el 20% de los llamados son de tipo Heavy y el 80% son más bien Soft/Light. Un Heavy Worker necesitará alrededor de 1 Gb de Ram, mientras que un Light Worker usará unos 150 Mb en las mismas condiciones. Es decir, y según coinciden en muchas webs especializadas, la recomendación actual es la siguiente:
5 Usuarios = 2 CPU y 2 Gb de Ram
20 Usuarios = 4 CPU y 8 Gb de Ram
+100 Usuarios = Se recomienda separar la Aplicación y Base de datos en dos servidores, cada uno con 8 CPU y 32 Gb de Ram.
Usar HTTPS con el protocolo correcto. En efecto, como muchos ya sabrán, HTTPS es -levemente- mas lento que HTTP, resalto el levemente ya que los beneficios en seguridad superan -por mucho- un rendimiento imperceptible en la carga. Sin embargo, como se comenta en este otro blog, HTTPS puede utilizar protocolos mucho más rapidos y modernos que HTTP, como el protocolo HTTP/2 que está altamente soportado por la mayoría de los navegadores. Así que sí, HTTPS es seguridad y velocidad, aconsejable.
Mantener el Servidor. Muchas veces un desarrollador de Odoo no tiene prácticamente conocimientos en el manejo de un server y simplemente se limita a contratar el servicio e instalar el framework. Otros desarrolladores simplemente consideran que el servidor debe ser mantenido por seguridad. Ambas posturas tienen parte de la razón, pero lo cierto es que el servidor tiene mucho peso en el rendimiento de nuestro ERP e incluso del Website, y no solo se limita a la seguridad (importante también). Un servidor en el cual ha pasado tiempo desde su instalación de Odoo necesita, por lo menos, hacer un update y upgrade de sus paquetes (por supuesto, consideramos que a estas alturas todos usamos distros de Linux). Se recomienda por temas de seguridad, pero también tiene impacto en el rendimiento, lo mismo que actualizar el sistema operativo cuando existan versiones estables. Y lo mismo ocurre con el wkpdftohtml, la librería por excelencia de Odoo para convertir los HTML de los reportes en un PDF para imprimir. Esta librería consume prácticamente un CPU entero a la hora de generar un reporte en PDF, más vale mantenerla actualizada por cualquier inconveniente (la actualización debe realizarse de forma manual, y junto con ella sus dependencias). Deben tenerse en cuenta, también, muchos factores invisibles que suelen afectar al rendimiento, como la generación de archivos de log. No nos malinterpreten, son extremadamente necesarios, pero a veces se acumulan sin razón. Más aún si compartimos el server con otras implementaciones (otros Odoo, incluso con un Drupal o Wordpress es algo habitual, o con un GitLab) estaremos generando archivos de log, archivos de control y otros elementos considerados "basura", que pueden acabar con la memoria en disco de nuestro Server. Una ocación nos ha pasado que el servidor funcionaba lento durante unas horas antes de quedarse sin memoria en disco, producto de una sincronización de un GitLab personal con GitHub. El resultado fue una memoria agotada, una baja considerable del rendimiento seguido de una caida completa del servidor (y por consecuencia un Odoo que se encontraba funcionando). Prestar mucha atención a como se maneja la memoria en disco del server a la hora de realizar un mantenimiento puede ayudarnos a mantener o incluso mejorar el pagespeed de nuestro website. Y si estamos teniendo muchos problemas con el TTFB (Time to First Byte) deberiamos hacer un repaso de todo lo instalado en el server, o considerar cambiar a un server mas óptimo.
Mantener Odoo actualizado. Es cierto que comentamos en otra entrada que migrar la versión de Odoo no es tan recomendable en la mayoría de los casos. La realidad es que el modelo de actualización anual de Odoo no es algo muy positivo para un desarrollador, pero desgraciadamente es el modelo que Odoo sigue aún a día de hoy. Seamos realistas, muy pocas empresas tienen la estructura como para pagar una actualización anual de un sistema tan complejo (especialmente si hay módulos personalizados involucrados) y aunque sobrasen d chas empresas, con el tiempo que demora es imposible encontrar la cantidad de programadores para todos. Pero el caso es que es muy aconsejable mantener el Odoo actualizado (o en lo posible los módulos, de terceros incluidos). No cada nueva versión, pero si considerarlo pasadas unas dos o tres versiones. La razón es muy simple: internet avanza. Antes de Odoo 9 no había forma nativa de incluir un servicio CDN a Odoo; antes de la nueva API se llamaba a una ingesta cantidad de archivos JavasScript (algo totalmente desaconsejable); ya GitHub dejó de usar jQuery, Odoo lo utiliza cada vez menos, en futuras versiones puede que ni exista como dependencia; y un largo etcétera. Y si, rara vez ocurre que entre versión y versión los cambios son tan abismales como lo fueron cuando se introdujo la nueva API. Pero pasadas un par de versiones notaremos como el framework no solo anda mejor, sino que trae herramientas acordes a los tiempos que corren. Así que la migración quedará en manos de los recursos de la empresa. Convengamos que entre una versión 8 y una 12 la optimización no es tan impresionante como parecería que deba ser, teniendo en cuenta las 4 versiones de diferencia (problema que ocurre al tratarse de una actualización anual).
Solucionar errores de consola. Mediante la tecla F12 podremos acceder a las herramientas de desarrollo del navegador. Es importante hacer revisiones periódicas de todo lo que pasa en la consola. Muchas veces un recursos mal cargado implica advertencias que pueden entorpecer el rendimiento, y también es una fuente constante de consejos actualizados sobre como estamos programando nuestros módulos de Odoo (especialmente el JavaScript). En otras situaciones suele advertirnos también de dependencias ausentes de Odoo, advertencias que mejor solucionar cuanto antes, ya que no sabemos como puede afectar al rendimiento futuro.
Emplear buenas herramientas de Pagespeed Test. Si el Pagespeed Test se usa sabiendo las limitaciones de nuestro Odoo y entendiendo que no se puede obtener la "perfección", entonces es un gran aliado para saber que problemáticas de rendimiento encarar. Lo ideal es no enloquecerse si nos dice que una imagen puede optimizarse para ahorrar 1 Kb. Pero a veces hay imágenes mal cargadas o información en el Caché de recursos de terceros que es importante conocer. Como todo en la vida hay buenos y malos recursos, nosotros solemos utilizar WebPageTest, nos resulta el más coherente al repetir un test y el que información más precisa provee. Además, permite testear de forma 100% gratuita con servidores en todas partes del mundo, distintos tipos de conexiones (cable, 3G, 4G, etc) y dispositivos (computadora de escritorio, android, iphone, etc).
Otras consideraciones. ¿Qué pasa si aún necesitamos más? En caso de querer adentrarse en el universo de un Pagespeed todavía más profundo, aconsejamos revisar las últimas recomendaciones en Pagespeed que se presentan por internet, ya que nuestro Odoo es -en esencia- un sitio web más. Algunos consejos para entendidos puede ser hacer uso minusioso del caché de archivos, programar el Garbage Collection de JavaScript, emplear herramientas de terceros -muchas veces pagas- especializadas en optimización (como puede ser Cloudflare o Fasterize), usar lazyloading en imágenes/videos, utilizar el módulo PageSpeed de Google, usar AMP de Google y emplear RXJS para la carga async de datos en JavaScript; entre otras miles de opciones que cada día surgen.
Acerca de:
Ignacio Buioli
Degree on Multimedia Arts. He has developed numerous Multimedia projects as well as written articles and translated texts of the mentioned subject. In Moldeo Interactive, He is a Partner and Programmer; also taking care of a large part of the online networks and courses.