Sirviendo CSS y JavaScript con gzip desde Amazon CloudFront a través de S3

196

He estado buscando formas de hacer que mi sitio se cargue más rápido y una forma que me gustaría explorar es hacer un mayor uso de Cloudfront.

Debido a que Cloudfront no se diseñó originalmente como una CDN de origen personalizado y debido a que no admitía gzipping, hasta ahora lo he estado usando para alojar todas mis imágenes, a las que se hace referencia por su cname de Cloudfront en el código de mi sitio, y optimizadas con far -futuros encabezados.

Los archivos CSS y javascript, por otro lado, están alojados en mi propio servidor, porque hasta ahora tenía la impresión de que no se podían servir con gzip desde Cloudfront, y que la ganancia de gzipping (alrededor del 75 por ciento) supera eso. por usar una CDN (aproximadamente el 50 por ciento): Amazon S3 (y por lo tanto Cloudfront) no admitía el servicio de contenido comprimido con gzip de manera estándar mediante el uso del encabezado HTTP Accept-Encoding que envían los navegadores para indicar su compatibilidad con la compresión gzip, y por lo que no pudieron hacer Gzip y servir componentes sobre la marcha.

Por tanto, tenía la impresión, hasta ahora, de que había que elegir entre dos alternativas:

  1. mueva todos los activos a Amazon CloudFront y olvídese de GZipping;

  2. mantener los componentes autohospedados y configurar nuestro servidor para detectar solicitudes entrantes y realizar GZipping sobre la marcha según corresponda, que es lo que elegí hacer hasta ahora.

No eran soluciones para resolver este problema, pero esencialmente éstos no funcionaron . [ enlace ].

Ahora, parece que Amazon Cloudfront admite el origen personalizado y que ahora es posible utilizar el método estándar de codificación de aceptación HTTP para entregar contenido comprimido con gzip si está utilizando un origen personalizado [ enlace ].

Hasta ahora no he podido implementar la nueva función en mi servidor. La publicación de blog a la que me vinculé anteriormente, que es la única que encontré que detalla el cambio, parece implicar que solo puede habilitar gzipping (soluciones alternativas de barra, que no quiero usar), si opta por un origen personalizado, que Preferiría no hacerlo: me resulta más sencillo alojar los archivos correspondientes en mi servidor Cloudfront y vincularlos desde allí. A pesar de leer detenidamente la documentación, no lo sé:

  • si la nueva función significa que los archivos deben alojarse en mi propio servidor de dominio a través de un origen personalizado y, de ser así, qué configuración de código logrará esto;

  • cómo configurar los encabezados css y javascript para asegurarse de que se publiquen en gzip desde Cloudfront.

0
205

ACTUALIZACIÓN: Amazon ahora admite la compresión gzip, por lo que ya no es necesaria. Anuncio de Amazon

Respuesta original:

La respuesta es gzip los archivos CSS y JavaScript. Sí, lo leiste bien.

gzip -9 production.min.css

Esto producirá production.min.css.gz. Elimine .gz, cárguelo en S3 (o cualquier servidor de origen que esté usando) y establezca explícitamente el Content-Encodingencabezado del archivo en gzip.

No se trata de gzip sobre la marcha, pero podría incluirlo fácilmente en sus scripts de compilación / implementación. Las ventajas son:

  1. Apache no requiere CPU para gzip el contenido cuando se solicita el archivo.
  2. Los archivos están comprimidos con gzip en el nivel de compresión más alto (suponiendo gzip -9).
  3. Estás sirviendo el archivo desde un CDN.

Suponiendo que sus archivos CSS / JavaScript están (a) minimizados y (b) lo suficientemente grandes como para justificar la CPU requerida para descomprimir en la máquina del usuario, puede obtener ganancias de rendimiento significativas aquí.

Solo recuerde: si realiza un cambio en un archivo que está almacenado en caché en CloudFront, asegúrese de invalidar el caché después de realizar este tipo de cambio.

12
  • 37
    Después de leer su enlace, debo decir que el autor del blog no está informado. "Sin embargo, si el usuario tiene un navegador que no admite la codificación gzip, las hojas de estilo comprimidas y los javascripts de su sitio simplemente no funcionarán para ese usuario". Es probable que este navegador sea demasiado antiguo para ejecutar sus hojas de estilo y archivos de script de todos modos. Estos usuarios constituyen una fracción de un porcentaje. 27 de marzo de 2011 a las 4:14
  • 3
    ACTUALIZACIÓN: Lo resolví. La razón por la que no se mostraba era que me había olvidado de establecer Content-Type en text / css. Si lo hace, está bien, aunque por alguna razón parece que no puede agregar un encabezado "Accept-Encoding: Vary" en S3 (lo que ayudaría con la calificación de velocidad de Google) por las razones que se describen aquí: [enlace ]. Además, configuré Cache-control para almacenar en caché el activo, pero no parece estar almacenando en caché ... 27/03/11 a las 12:07
  • 32
    Acabo de encontrar esto a través de Google, y lamento tener que decir que este no es un buen consejo. Mientras que <1% de los navegadores de escritorio no pueden manejar contenido comprimido con gzip, muchos navegadores móviles no pueden. La cantidad depende de qué público objetivo esté mirando; pero la mayoría de los Nokia S40 más antiguos tienen compresión gzip defectuosa, por ejemplo. La forma correcta es un "Origen personalizado", que apunta a un servidor web Apache / IIS que comprime el contenido y sirve los encabezados HTTP adecuados. Aquí hay una publicación de blog que describe la esencia de la misma: nomitor.com/blog/2010/11/10/… 28/07/11 a las 23:18
  • 14
    ¿Cómo está la situación ahora, a principios de 2015? ¿Siguen siendo relevantes los enlaces publicados por @JesperMortensen y Simon Peck? 14 de enero de 2015 a las 15:09
  • 5
    Amazon anunció el soporte para la compresión gzip en diciembre de 2015, por lo que ahora es irrelevante, solo cargue el archivo básico y funcionará. aws.amazon.com/blogs/aws/…
    Sean
    2 de febrero de 2016 a las 16:10
15

Mi respuesta es un despegue en esto: http://blog.kenweiner.com/2009/08/serving-gzipped-javascript-files-from.html

Partiendo de la respuesta de skyler, puede cargar una versión gzip y no gzip de css y js. Tenga cuidado al nombrar y probar en Safari. Porque safari no manejará .css.gzni .js.gzarchivos.

site.jsy site.js.jgzy site.cssy site.gz.css (deberá configurar el content-encodingencabezado en el tipo MIME correcto para que estos funcionen correctamente)

Luego, en tu página pon.

<script type="text/javascript">var sr_gzipEnabled = false;</script> 
<script type="text/javascript" src="http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr.gzipcheck.js.jgz"></script> 

<noscript> 
  <link type="text/css" rel="stylesheet" href="http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css">
</noscript> 
<script type="text/javascript"> 
(function () {
    var sr_css_file = 'http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css';
    if (sr_gzipEnabled) {
      sr_css_file = 'http://d2ft4b0ve1aur1.cloudfront.net/css-050/sr-br-min.css.gz';
    }

    var head = document.getElementsByTagName("head")[0];
    if (head) {
        var scriptStyles = document.createElement("link");
        scriptStyles.rel = "stylesheet";
        scriptStyles.type = "text/css";
        scriptStyles.href = sr_css_file;
        head.appendChild(scriptStyles);
        //alert('adding css to header:'+sr_css_file);
     }
}());
</script> 

gzipcheck.js.jgz es solo sr_gzipEnabled = true; Esta prueba para asegurarse de que el navegador puede manejar el código comprimido con gzip y proporcionar una copia de seguridad si no puede.

Luego haga algo similar en el pie de página asumiendo que todos sus js están en un archivo y pueden ir en el pie de página.

<div id="sr_js"></div> 
<script type="text/javascript"> 
(function () {
    var sr_js_file = 'http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr-br-min.js';
    if (sr_gzipEnabled) {
       sr_js_file = 'http://d2ft4b0ve1aur1.cloudfront.net/js-050/sr-br-min.js.jgz';
    }
    var sr_script_tag = document.getElementById("sr_js");         
    if (sr_script_tag) {
    var scriptStyles = document.createElement("script");
    scriptStyles.type = "text/javascript";
    scriptStyles.src = sr_js_file;
    sr_script_tag.appendChild(scriptStyles);
    //alert('adding js to footer:'+sr_js_file);
    }
}());
</script> 

ACTUALIZACIÓN: Amazon ahora admite la compresión gzip. Anuncio, por lo que ya no es necesario. Anuncio de Amazon

3
  • muchas gracias por esa sugerencia. Si le entiendo correctamente, está abordando el caso en el que el navegador del usuario no puede leer el archivo comprimido con gzip, lo que aún puede ocurrir aunque se trate de un porcentaje bastante pequeño de navegadores en la actualidad. Un posible inconveniente de esta solución, si consulta el enlace que publiqué en mi pregunta [enlace ] es que significa que no puede almacenar en caché su página, ya que solo funcionará si su código se ejecuta dinámicamente cada vez que un usuario carga la página (que por supuesto es la mía). 1 de abril de 2011 a las 6:57
  • @DonaldJenkins Creo que los js todavía se almacenarán en caché. Cuando crea la etiqueta de script en el js snip, aún debe llamarse a js y creo que si está en la caché, el navegador lo usaría desde allí.
    Sean
    25/07/12 a las 15:50
  • 2
    La página de prueba blog.kosny.com/testpages/safari-gz indica que la advertencia "Tenga cuidado al nombrar y probar en Safari. Porque safari no manejará css.gz o js.gz" está desactualizada. En Safari 7 en Mavericks y en Safari en iOS 7, funcionan tanto css.gz como js.gz. No sé cuándo ocurrió este cambio, solo estoy probando con los dispositivos que tengo.
    garyrob
    14/11/2013 a las 15:46
14

Cloudfront admite gzip.

Cloudfront se conecta a su servidor a través de HTTP 1.0. De forma predeterminada, algunos servidores web, incluido nginx, no sirven contenido comprimido con gzip en conexiones HTTP 1.0, pero puede indicarle que lo haga agregando:

gzip_http_version 1.0

a su configuración de nginx. La configuración equivalente podría establecerse para cualquier servidor web que esté utilizando.

Esto tiene el efecto secundario de hacer que las conexiones de mantenimiento no funcionen para las conexiones HTTP 1.0, pero como los beneficios de la compresión son enormes, definitivamente vale la pena el compromiso.

Tomado de http://www.cdnplanet.com/blog/gzip-nginx-cloudfront/

Editar

Ofrecer contenido comprimido con gzip sobre la marcha a través del frente de la nube de Amazon es peligroso y probablemente no debería hacerse. Básicamente, si su servidor web está comprimiendo el contenido con gzip, no establecerá una Longitud de contenido y, en su lugar, enviará los datos como fragmentados.

Si la conexión entre Cloudfront y su servidor se interrumpe y se corta prematuramente, Cloudfront aún almacena en caché el resultado parcial y lo sirve como la versión en caché hasta que expire.

La respuesta aceptada de gziplo primero en el disco y luego entregar la versión gzip es una mejor idea, ya que Nginx podrá configurar el encabezado Content-Length, por lo que Cloudfront descartará las versiones truncadas.

4
  • 5
    -1, esta respuesta no tiene nada que ver con la pregunta. Nginx! = S3 y Cloudfront 1 de mayo de 2013 a las 19:40
  • @Danack, ¿experimentó muchos problemas con Cloudfront almacenando en caché los archivos medio recuperados debido a este problema? Estoy tratando de entender cuán problemático fue esto para ti en la práctica.
    poshest
    24/0316 a las 10:35
  • 1
    @poshest Sucedió. Hubo muy pocos beneficios en servir gzip sobre la marcha (ya que gzip es tan rápido en el servidor de todos modos), así que lo apagué tan pronto como vi que sucedía. Los datos dañados son un problema mucho mayor que tener un "tiempo para el primer byte" que sea 200ms lento en los raros casos en los que el contenido no existe ya en formato gzip.
    Danack
    24/03/2016 a las 21:45
  • Si a un activo le falta una propiedad Content-Length en el encabezado, pero incluye Transfer-Encoding: fragmentado (como suele ser el caso de los activos comprimidos con gzip), CloudFront NO almacenará en caché un activo parcial si no recibe un fragmento de terminación. Si faltan estas dos propiedades, es posible que se almacene en caché un activo incompleto. Ver: docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/… 14/04/2017 a las 18:24
5

Recientemente, hicimos algunas optimizaciones para uSwitch.com para comprimir algunos de los activos estáticos en nuestro sitio. Aunque configuramos un proxy nginx completo para hacer esto, también he creado una pequeña aplicación de Heroku que actúa como proxy entre CloudFront y S3 para comprimir contenido: http://dfl8.co

Dado que se puede acceder a los objetos S3 de acceso público utilizando una estructura de URL simple, http://dfl8.co simplemente usa la misma estructura. Es decir, las siguientes URL son equivalentes:

http://pingles-example.s3.amazonaws.com/sample.css
http://pingles-example.dfl8.co/sample.css
http://d1a4f3qx63eykc.cloudfront.net/sample.css
0
5

Ayer, Amazon anunció una nueva función, ahora puede habilitar gzip en su distribución.

Funciona con s3 sin archivos .gz agregados, probé la nueva característica hoy y funciona muy bien. (aunque es necesario invalidar sus objetos actuales)

Más información

0
0

Puede configurar CloudFront para comprimir automáticamente archivos de ciertos tipos y entregar los archivos comprimidos.

Consulte la guía para desarrolladores de AWS

1
  • ¿Puede agregar más información sobre su solución (tal vez un ejemplo) para que sea una mejor respuesta? 6 de julio de 2017 a las 8:17