6 formas rápidas y sencillas de acelerar tu sitio web en Laravel
- Publicado el 17 septiembre, 2024
- Palabras: 2340
Se estima que el 40 % de las personas abandonan un sitio web si tarda más de 3 segundos en cargarse. Por lo tanto, es sumamente importante desde un punto de vista comercial asegurarse de no superar ese umbral de 3 segundos.
Por lo tanto, siempre que escribo código para mis nuevos proyectos de Laravel, trato de asegurarme de optimizar el código tanto como sea posible dentro de mis limitaciones de tiempo y costo. Si alguna vez trabajo en algún proyecto existente, también trato de usar estas técnicas para actualizar cualquier código de ejecución lenta para optimizar el rendimiento de la aplicación de Laravel. Esto no solo hace que la aplicación de Laravel sea más rápida, sino que también puede mejorar la experiencia general para los usuarios.
A continuación, se muestran algunas de las técnicas que uso (o sugiero a otros desarrolladores) para obtener algunas mejoras rápidas en el rendimiento de mis sitios web y aplicaciones de Laravel y los de mis clientes.
1. Obtén únicamente los campos que necesita en las consultas de su base de datos
Una forma sencilla de acelerar su sitio Laravel es reducir la cantidad de datos transferidos entre su aplicación y la base de datos. Una forma de hacerlo es especificando solo las columnas que necesita en sus consultas mediante una cláusula select.
A modo de ejemplo, supongamos que tiene un modelo de usuario que contiene 20 campos diferentes. Ahora, imagine que tiene 10 000 usuarios en su sistema y está intentando realizar algún tipo de procesamiento en cada uno de ellos. Su código podría verse así:
$users = User::all();
foreach($users as $user) {
// Do something here
}
La consulta anterior sería responsable de recuperar 200.000 campos de datos. Pero, imagina que cuando estás procesando cada usuario, solo utilizas los campos id, first_name y last_name. Esto significa que de los 20 campos que estás recuperando, 17 de ellos son más o menos redundantes para este fragmento de código en particular. Por lo tanto, lo que podemos hacer es definir explícitamente los campos que se devuelven en la consulta. En este caso, tu código podría verse así:
$users = User::select([‘id’, ‘first_name’, ‘last_name’])->get();
foreach($users as $user) {
// Do something here
}
Al hacer esto, habremos reducido la cantidad de campos devueltos en la consulta de 200.000 a 30.000. Aunque esto probablemente no tendría mucho efecto en la carga de E/S de la base de datos, reduciría el tráfico de red entre tu aplicación y la base de datos. Esto se debe a que (presumiblemente) habría menos datos para serializar, enviar y luego deserializar que si tuvieras que recuperar todos los campos disponibles. Al reducir el tráfico de red y la cantidad de datos que se deben procesar, esto ayudaría a acelerar tu sitio Laravel.
Tenga en cuenta que, en el ejemplo anterior, es posible que nunca haga algo como esto y que probablemente utilice chunks o paginación según la situación. El ejemplo es solo para mostrar una solución posible y fácil de implementar.
Es posible que esta solución no le proporcione grandes mejoras en un sitio o aplicación más pequeños. Sin embargo, es algo que definitivamente puede ayudar a reducir los tiempos de carga en aplicaciones donde el rendimiento es un factor importante. También puede ver mejoras más importantes si está consultando una tabla que tiene campos BLOB o TEXT. Estos campos pueden contener potencialmente megabytes de datos y, por lo tanto, pueden aumentar el tiempo de consulta. Por lo tanto, si la tabla de su modelo contiene alguno de estos campos, considere definir explícitamente los campos que necesita en su consulta para reducir el tiempo de carga.
2. Utilice eager loading (carga anticipada) siempre que sea posible
Cuando estás recuperando modelos de la base de datos y luego haciendo cualquier tipo de procesamiento en las relaciones del modelo, es importante que uses la eager loading. El eager loading es muy simple usando Laravel y básicamente evita que te encuentres con el problema N+1 con tus datos. Este problema es causado por hacer N+1 consultas a la base de datos, donde N es la cantidad de elementos que se recuperan de la base de datos. Para explicar esto mejor y darle un poco de contexto, veamos el siguiente ejemplo.
Imagina que tienes dos modelos (Comment y Author) con una relación uno a uno entre ellos. Ahora imagina que tienes 100 comentarios y quieres recorrer cada uno de ellos y mostrar el nombre del autor.
Sin eager loading, tu código podría verse así:
$comments = Comment::all();
foreach ($comments as $comment ) {
print_r($comment->author->name);
}
El código anterior generaría 101 consultas a la base de datos. La primera consulta sería para obtener todos los comentarios. Las otras cien consultas provendrían de obtener el nombre del autor en cada iteración del bucle. Obviamente, esto puede causar problemas de rendimiento y ralentizar la aplicación. Entonces, ¿cómo mejoraríamos esto?
Al usar eager loading, podríamos cambiar el código para que diga:
$comments = Comment::with(‘authors’)->get();
foreach ($comments as $comment ) {
print_r($comment->author->name);
}
Como puedes ver, este código se ve casi igual y todavía es legible. Al agregar ::with('authors') se obtendrán todos los comentarios y luego se realizará otra consulta para obtener los autores a la vez. Esto significa que habremos reducido la consulta de 101 a 2.
¡Esto puede mejorar drásticamente el rendimiento de tu aplicación y acelerar tu sitio web de Laravel!
Para obtener más información, consulta la documentación de Laravel sobre eager loading.
3. Deshazte de cualquier paquete innecesario o no deseado
Abre tu archivo composer.json y revisa cada una de tus dependencias. Para cada una de tus dependencias, pregúntate "¿realmente necesito este paquete?". Tu respuesta será en su mayoría sí, pero para algunas de ellas puede que no lo sea.
Cada vez que incluyes una nueva biblioteca Composer en tu proyecto, estás potencialmente agregando código adicional que podría ejecutarse innecesariamente. Los paquetes de Laravel generalmente contienen servie providers (proveedores de servicios) que se ejecutan en cada solicitud que registra servicios y ejecuta código. Entonces, digamos que agregas 20 paquetes de Laravel a tu aplicación, eso probablemente significa que se instancian y ejecutan un mínimo de 20 clases en cada solicitud. Aunque esto no tendrá un gran impacto en el rendimiento de los sitios o aplicaciones con pequeñas cantidades de tráfico, definitivamente podrás notar la diferencia en aplicaciones más grandes.
La solución a esto es determinar si realmente necesitas todos los paquetes.
Tal vez estés usando un paquete que ofrece una variedad de funciones, pero en realidad solo estás usando una pequeña función de ellas. Pregúntate "¿podría escribir este código yo mismo y eliminar todo este paquete?" Por supuesto, debido a las limitaciones de tiempo, no siempre es posible escribir el código tú mismo porque tendrás que escribirlo, probarlo y luego mantenerlo. Al menos, al usar el paquete, estás aprovechando la comunidad de código abierto para que haga esas cosas por ti. Pero, si un paquete es simple y rápido de reemplazar con tu propio código, entonces consideraría eliminarlo.
4. Cache, cache, cache!
Laravel viene con muchos métodos de almacenamiento en caché listos para usar. Estos pueden hacer que sea muy fácil acelerar su sitio web o aplicación mientras está en línea sin necesidad de realizar ningún cambio de código.
Almacenamiento en caché de rutas
Debido a la forma en que se ejecuta Laravel, inicia el framework y analiza el archivo de rutas en cada solicitud que se realiza. Esto requiere leer el archivo, analizar su contenido y luego guardarlo de una manera que su aplicación pueda usar y comprender. Entonces, Laravel proporciona un comando que puede usar y que crea un solo archivo de rutas que se puede analizar mucho más rápido:
php artisan route:cache
Sin embargo, tenga en cuenta que si usa este comando y cambia sus rutas, deberá asegurarse de ejecutar:
php artisan route:clear
Esto eliminará el archivo de rutas almacenadas en caché para que se puedan registrar las rutas más nuevas. Puede que valga la pena agregar estos dos comandos a su script de despliege si aún no lo tiene.
Config caching
De manera similar al almacenamiento en caché de rutas, cada vez que se realiza una solicitud, se inicia Laravel y se leen y analizan todos los archivos de configuración de su proyecto. Por lo tanto, para evitar que sea necesario procesar cada uno de los archivos, puede ejecutar el siguiente comando que creará un archivo de configuración en caché:
php artisan config:cache
Sin embargo, al igual que con el almacenamiento en caché de rutas mencionado anteriormente, deberá recordar ejecutar el siguiente comando cada vez que actualice su archivo .env o sus archivos de configuración:
php artisan config:clear
En el pasado, he visto a muchos desarrolladores almacenar en caché su configuración en su entorno de desarrollo local y luego pasar mucho tiempo tratando de averiguar por qué los cambios en su archivo .env no se muestran. Por lo tanto, probablemente recomendaría almacenar en caché su configuración y rutas solo en sistemas en producción para no terminar en la misma situación.
Consultas y valores de almacenamiento en caché
Dentro del código de tu aplicación Laravel, puedes almacenar en caché elementos para mejorar el rendimiento del sitio web. Como ejemplo, imagina que tienes la siguiente consulta:
$users = DB::table('users')->get();
Para utilizar el almacenamiento en caché con esta consulta, puede actualizar el código a lo siguiente:
$users = Cache::remember('users', 120, function () {
return DB::table('users')->get();
});
El código anterior utiliza el método remember(). Básicamente, lo que hace es abrir comprobaciones para ver si el caché contiene algún elemento con la clave users. Si es así, devuelve el valor almacenado en caché. Si no existe en el caché, se devolverá el resultado de la consulta DB::table('users')->get() y también se almacenará en caché. En este ejemplo en particular, el elemento se almacenaría en caché durante 120 segundos.
Almacenar en caché los datos y los resultados de las consultas de esta manera puede ser una forma muy eficaz de reducir las llamadas a la base de datos, reducir el tiempo de ejecución y mejorar el rendimiento. Sin embargo, es importante recordar que, en ocasiones, es posible que deba eliminar el elemento del caché si ya no es válido.
Utilizando el ejemplo anterior, imagine que tenemos la consulta users almacenada en caché. Ahora imagine que se ha creado, actualizado o eliminado un nuevo usuario. Ese resultado de la consulta almacenado en caché ya no será válido ni estará actualizado. Para solucionar este problema, podríamos utilizar los observadores del modelo de Laravel para eliminar este elemento del caché. Esto significa que la próxima vez que intentemos obtener la variable $users, se ejecutará una nueva consulta de base de datos que nos dará el resultado actualizado.
5. Utilice la última versión de PHP
Con cada nueva versión de PHP que sale, el rendimiento y la velocidad mejoran. Kinsta realizó muchas pruebas en varias versiones de PHP y diferentes plataformas (por ejemplo, Laravel, WordPress, Drupal, Joomla) y descubrió que PHP 8.3 ofrecía el mejor aumento de rendimiento.
Este consejo en particular puede ser un poco más difícil de implementar en comparación con los otros consejos anteriores porque necesitará auditar su código para asegurarse de que puede actualizar de manera segura a la última versión de PHP. Como nota al margen, ¡tener un conjunto de pruebas automatizadas puede ayudarlo a tener la confianza para realizar esta actualización!
6. Hacer uso de las colas de trabajo
Este consejo puede llevar un poco más de tiempo que algunos de los otros consejos basados en código anteriores para implementarse. A pesar de esto, este consejo probablemente será uno de los más gratificantes en términos de experiencia del usuario.
Una forma de reducir el tiempo de rendimiento es hacer uso de las colas de Laravel. Si hay algún código que se ejecuta en su controlador o clases en una solicitud que no es particularmente necesario para la respuesta del navegador web, generalmente podemos ponerlo en cola.
Para que sea más fácil de entender, consulte este ejemplo:
class ContactController extends Controller
{
/**
* Store a new podcast.
*
* @param Request $request
* @return JsonResponse
*/
public function store(ContactFormRequest $request)
{
$request->storeContactFormDetails();
Mail::to('mail@ashallendesign.co.uk')->send(new ContactFormSubmission);
return response()->json(['success' => true]);
}
}
En el código anterior, cuando se invoca el método store(), este almacena los detalles del formulario de contacto en la base de datos, envía un correo electrónico a una dirección para informarle sobre un nuevo envío del formulario de contacto y devuelve una respuesta JSON. El problema con este código es que el usuario tendrá que esperar hasta que se haya enviado el correo electrónico antes de recibir su respuesta en el navegador web. Aunque esto puede tardar solo unos segundos, puede hacer que los visitantes se vayan.
Para utilizar el sistema de colas, podríamos actualizar el código a lo siguiente:
class ContactController extends Controller
{
/**
* Store a new podcast.
*
* @param Request $request
* @return JsonResponse
*/
public function store(ContactFormRequest $request)
{
$request->storeContactFormDetails();
dispatch(function () {
Mail::to('mail@ashallendesign.co.uk')->send(new ContactFormSubmission);
})->afterResponse();
return response()->json(['success' => true]);
}
}
El código anterior en el método store() almacenará ahora los detalles del formulario de contacto en la base de datos, pondrá en cola el correo para enviarlo y luego devolverá la respuesta. Una vez que la respuesta se haya enviado de vuelta al navegador web del usuario, el correo electrónico se agregará a la cola para que pueda procesarse. Al hacer esto, significa que no necesitamos esperar a que se envíe el correo electrónico antes de devolver la respuesta.
Consulta la documentación de Laravel para obtener más información sobre cómo configurar las colas para tu sitio web o aplicación de Laravel.
¿Necesitas ayuda?
Si necesitas ayuda o consejos sobre cómo implementar estos consejos en tu aplicación Laravel, no dudes en enviarme un mensaje y ponerte en contacto conmigo. También ofrezco un servicio de desarrollo web Laravel si te interesa que agregue estas optimizaciones para ti.
Antonio Jenaro
Web Developer
Fuente: Ash Allen Design
Inicia la conversación
Hazte miembro de Antonio Jenaro para comenzar a comentar.
Regístrate ahora¿Ya estás registrado? Inicia sesión