Mejoras de rendimiento en una aplicación Symfony 2

Hoy en dia una pagina web o sitio web, tiene que tener un rendimiento optimo en cuanto a velocidad de carga de la misma para que el usuario no se canse y se marche, y ademas para que Google no nos penalice a nivel de SEO por culpa del rendimiento.

Existen multitud de herramientas que analizan el rendimiento de un sitio web y te dan indicaciones sobre algunos elementos “mejorables” para optimizar el rendimiento.

Entre estas herramientas destaco:

– https://developers.google.com/speed/pagespeed/insights/

– https://gtmetrix.com/ (De pago)

A continuación explico algunos de las indicaciones que muestran estas herramientas y las soluciones que hemos aplicado en un proyecto Symfony 2.

Listado de sugerencias a nivel de proyecto:

– Comprimir todas las images usando la tecnica de sprites CSS: Consiste en juntar todas las imagenes del mismo tamaño o similar en una sola y mediante CSS mostrarla para que solo haga una peticion en lugar de N una por cada imagen. Podeis usar esta web(http://spritegen.website-performance.org/) para que os junte todas las imagenes y ademas os genere el CSS / LESS con las posiciones de cada imagen. Estamuy bien, la recomiendo 100%.

Minificar Css /Js: Nos dimos cuenta que al generar los assets en producción, no se aplicaban los filtros de uglilfyCSS y uglifyJS. Me puse a investigar y es que para que se compriman los assets el comando necesita de un parametro adicional, tal que asi:

>>php app/console assetic:dump –env=prod

Especificar caché de navegador: Para que el navegador pueda cachear los ficheros y servirlos mas rápido, hay que tocar el archivo .htaccess de la siguiente forma:

# cacheo de elementos estaticos. Edad maxima de las cabeceras HTTP
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpg                             "access 2 hour"
    ExpiresByType image/jpeg                            "access 2 hour"
    ExpiresByType image/gif                             "access 2 hour"
    ExpiresByType image/png                             "access 2 hour"
    ExpiresByType application/pdf                       "access 2 hour"
    ExpiresByType image/x-icon                          "access 2 hour"

    ExpiresByType text/css                              "access 1 week"

    ExpiresByType text/x-javascript                     "access 1 week"
    ExpiresByType text/js                               "access 1 week"
    ExpiresByType text/javascript                       "access 1 week"
    ExpiresByType application/javascript                "access 1 week"

    ExpiresByType application/font-woff                 "access 1 week"
    ExpiresByType application/vnd.ms-fontobject         "access 1 week"
    ExpiresByType application/x-font-ttf                "access 1 week"
    ExpiresByType font/opentype                         "access 1 week"
    ExpiresByType image/svg+xml                         "access 1 week"

    # Para evitar el cacheo con la sesion del usuario por cachear el contenido estatico HTML
    <filesmatch ".(xml|txt|html|php)$">
        ExpiresDefault A0 #no cacheo
    </filesmatch>

    ExpiresDefault A3600 #por defecto 1h
</IfModule>

En nuestro caso, las imagenes las cacheamos solo por 2h por que como son dinámicas y puede que los usuarios las modifiquen frecuentemente, no pueden estar mucho tiempo en cache para que se refresquen cuanto antes(cada 2h). Para el resto, Css, Js, y fuentes, las cacheamos durante 1 semana. Para los archivos HTML, Php, etc. forzamos a que NUNCA se cacheen, para evitar problemas con sesiones de usuarios, etc.

Minificar el HTML: Como en el proyecto se usa TWIG como motor de plantillas, existe la función {% spaceless %}{% endespaceless %} que elimina los espacios en el código HTML generado por Twig, de esa forma reducimos el tamaño de los ficheros HTML generados. (http://twig.sensiolabs.org/doc/tags/spaceless.html). Lo ideal es ponerlo en el base.html.twig por encima de los tags {% spaceless %}<html></html>{% endspaceless %}.

Uso de un CDN: De las siglas Content Delivery Network, es un servidor intermedio que cachea el contenido estatico para servirlo con mas rapidez entre los clientes y el servidor, reduciendo asi el tiempo de espera y ademas la carga del servidor por la cantidad de peticiones o requests que recibe y responde.

En nuestro caso, usamos MaxCDN un servicio que nos ofrece cacheo estatico en todos los dominios o subdominios que necesitemos. Es de pago, obviamente, pero funciona bien. Solo hayq ue añadir en el htccess un bloque ellos mismos te dan para que el navegador pueda descargarse correctamente el contenido y añadir en el config.yml lo siguiente para que los estaticos en PRODUCCIÓN los coja del CDN, pero los de DESAROLLO coja los locales.

– .htaccess:

# Para que el CDN no bloquee los iconos y las fuentes debido al cross domain 
# ----------------------------------------------------------------------
# CORS-enabled images (@crossorigin)
# ----------------------------------------------------------------------
# Send CORS headers if browsers request them; enabled by default for images.
# developer.mozilla.org/en/CORS_Enabled_Image
# blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
# hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/
# wiki.mozilla.org/Security/Reviews/crossoriginAttribute
<IfModule mod_setenvif.c>
  <IfModule mod_headers.c>
    # mod_headers, y u no match by Content-Type?!
    <FilesMatch "\.(gif|png|jpeg|jpg|svg|svgz|ico|webp|eot)$">
      SetEnvIf Origin ":" IS_CORS
      Header set Access-Control-Allow-Origin "*" env=IS_CORS
    </FilesMatch>
  </IfModule>
</IfModule>
# ----------------------------------------------------------------------
# Webfont access
# ----------------------------------------------------------------------
# Allow access from all domains for webfonts.
# Alternatively you could only whitelist your
# subdomains like "subdomain.example.com".
<IfModule mod_headers.c>
  <FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$">
    Header set Access-Control-Allow-Origin "*"
  </FilesMatch>
</IfModule>

– config_prod.yml

framework:
    templating:
        assets_base_urls:
            http: ["https://XXXX-%locale%-XXXXX.netdna-ssl.com"]
            ssl: ["https://XXXX-%locale%-XXXXX.netdna-ssl.com"]

En nuestro caso, existen varias zonas una por cada idioma dela web definidas en el CDN y que dependen del locale de la aplicación, por eso usamos el %locale% como parte de la URI de acceso al CDN.

-Como documentación adicional, añado estas slides que he encontrado por internet.

http://slides.liip.ch/static/2012-05-18_symfony-speed.html

Listado de sugerencias a nivel de servidor:

-Como recomendación os digo que os creéis una maquina virtual y os instaléis el proyecto en ella para que no se rompa nada en producción(si ya tenéis vuestro proyecto en marcha) para poder deshacer todos los cambios.

PROXIMAMENTE…

 

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s