Exibição de CSS e JavaScript compactados com gzip no Amazon CloudFront via S3

194

Eu tenho procurado maneiras de tornar meu site carregado mais rapidamente e uma maneira que eu gostaria de explorar é fazer um uso maior do Cloudfront.

Como o Cloudfront não foi originalmente projetado como uma CDN de origem personalizada e porque não suporta gzipping, até agora eu o tenho usado para hospedar todas as minhas imagens, que são referenciadas por seu nome de usuário do Cloudfront no código do meu site e otimizadas com muito -futures cabeçalhos.

Os arquivos CSS e javascript, por outro lado, estão hospedados no meu próprio servidor, porque até agora eu tinha a impressão de que eles não podiam ser servidos com gzip no Cloudfront e que o ganho com gzipping (cerca de 75%) supera esse valor. do uso de uma CDN (cerca de 50%): o Amazon S3 (e, portanto, o Cloudfront) não suportava a veiculação de conteúdo compactado com gzip de maneira padrão, usando o cabeçalho HTTP Accept-Encoding enviado pelos navegadores para indicar seu suporte à compactação gzip, e então eles não foram capazes de compactar e servir componentes rapidamente.

Assim, tive a impressão, até agora, de que era preciso escolher entre duas alternativas:

  1. mova todos os ativos para o Amazon CloudFront e esqueça o GZipping;

  2. mantenha os componentes auto-hospedados e configure nosso servidor para detectar solicitações recebidas e executar GZipping on-the-fly conforme apropriado, que foi o que eu escolhi até agora.

Não foram soluções alternativas para resolver este problema, mas essencialmente estas não funcionou . [ link ].

Agora, parece Amazon CloudFront oferece suporte a origem costume, e que agora é possível usar o método padrão HTTP Accept-Encoding para servir conteúdo compactado se você estiver usando uma origem personalizado [ ligação ].

Até o momento, não consegui implementar o novo recurso no meu servidor. A postagem do blog que eu vinculei acima, que é a única que encontrei detalhando a alteração, parece implicar que você só pode ativar o gzipping (soluções alternativas de barra, que eu não quero usar), se você optar pela origem personalizada, que Prefiro não: acho mais simples hospedar os arquivamentos correspondentes no meu servidor Cloudfront e vincular a eles a partir daí. Apesar de ler atentamente a documentação, não sei:

  • se o novo recurso significa que os arquivos devem ser hospedados no meu próprio servidor de domínio por origem personalizada e, em caso afirmativo, qual configuração de código conseguirá isso;

  • como configurar os cabeçalhos css e javascript para garantir que eles sejam exibidos com gzip no Cloudfront.

Donald Jenkins
fonte

Respostas:

202

ATUALIZAÇÃO: a Amazon agora suporta compactação gzip, portanto, isso não é mais necessário. Anúncio da Amazon

Resposta original:

A resposta é compactar os arquivos CSS e JavaScript. Sim, você leu certo.

gzip -9 production.min.css

Isso irá produzir production.min.css.gz. Remova o .gz, faça o upload para o S3 (ou qualquer servidor de origem que você esteja usando) e defina explicitamente o Content-Encodingcabeçalho do arquivo gzip.

Não é um gzip on-the-fly, mas você pode facilmente envolvê-lo em seus scripts de construção / implantação. As vantagens são:

  1. Não requer CPU para o Apache compactar o conteúdo quando o arquivo for solicitado.
  2. Os arquivos são compactados no nível mais alto de compactação (assumindo gzip -9).
  3. Você está servindo o arquivo de uma CDN.

Supondo que seus arquivos CSS / JavaScript sejam (a) minificados e (b) grandes o suficiente para justificar a CPU necessária para descompactar na máquina do usuário, você pode obter ganhos de desempenho significativos aqui.

Lembre-se: se você fizer uma alteração em um arquivo armazenado em cache no CloudFront, certifique-se de invalidar o cache após fazer esse tipo de alteração.

Skyler Johnson
fonte
37
Depois de ler seu link, devo dizer que o autor do blog não está informado. "No entanto, se o usuário tiver um navegador que não suporte a codificação gzip, as folhas de estilo e javascripts zipados do seu site simplesmente não funcionarão para esse usuário." Esse navegador provavelmente seria muito antigo para executar suas folhas de estilo e arquivos de script de qualquer maneira. Esses usuários representam uma fração de um por cento.
precisa
3
ATUALIZAÇÃO: Eu resolvi. O motivo pelo qual não estava sendo exibido foi que eu havia me esquecido de definir o Tipo de conteúdo como text / css. Se você fizer isso, está bem, embora, por algum motivo, pareça não poder adicionar um cabeçalho "Accept-Encoding: Vary" no S3 (o que ajudaria na classificação do Google Speed) pelos motivos descritos aqui: [link ] Além disso, eu definir Cache-controle para armazenar em cache o ativo, mas não parece ser cache-lo ...
Donald Jenkins
32
Acabei de encontrar isso pelo Google e lamento ter que dizer que esse não é um bom conselho. Enquanto <1% dos navegadores de desktop não conseguem lidar com conteúdo compactado com gzip, muitos navegadores móveis não conseguem. Quantas depende de qual público-alvo você está vendo; mas a maioria dos Nokia S40 mais antigos tem compressão de buggy gzip, por exemplo. A maneira correta é uma "Origem personalizada", que aponta para um servidor da web Apache / IIS que compacta o conteúdo e serve os cabeçalhos HTTP adequados. Aqui está um post do blog que descreve a essência do mesmo: nomitor.com/blog/2010/11/10/…
Jesper M
14
Como está a situação agora, no início de 2015? Os links publicados por @JesperMortensen e Simon Peck ainda são relevantes?
usar o seguinte código
5
A Amazon anunciou o suporte à compactação gzip em dezembro de 2015, portanto, agora é irrelevante apenas fazer o upload do arquivo básico e funcionará. aws.amazon.com/blogs/aws/…
Sean
15

Minha resposta é a seguinte: http://blog.kenweiner.com/2009/08/serving-gzipped-javascript-files-from.html

Criando a resposta do skyler, você pode fazer upload de uma versão gzip e não gzip do css e js. Seja cuidadoso na nomeação e teste no Safari. Porque safari não vai lidar com .css.gzou .js.gzarquivos.

site.jsand site.js.jgzand site.cssand site.gz.css (você precisará definir o content-encodingcabeçalho para o tipo MIME correto para que ele funcione corretamente)

Em seguida, em sua página colocar.

<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 é apenas sr_gzipEnabled = true; Isso testa para garantir que o navegador possa manipular o código compactado com gzip e fornecer um backup, se não puderem.

Em seguida, faça algo semelhante no rodapé, assumindo que todos os seus js estejam em um arquivo e possam ir no rodapé.

<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> 

ATUALIZAÇÃO: A Amazon agora suporta compactação gzip. Anúncio, então isso não é mais necessário. Anúncio da Amazon

Sean
fonte
muito obrigado por essa sugestão. Se bem entendi, você está abordando o caso em que o navegador do usuário não consegue ler o arquivo compactado com gzip, o que ainda pode ocorrer, embora hoje em dia se refira a uma porcentagem bastante pequena de navegadores. Uma possível desvantagem desta solução, se você se referir ao link que eu postei na minha pergunta [link ] é que isso significa que você não pode armazenar em cache sua página, pois funcionará apenas se seu código for executado dinamicamente sempre que um usuário carregar a página (que obviamente é minha).
101911 Donald Jenkins
@DonaldJenkins Acho que os js ainda serão armazenados em cache. Quando você cria a tag de script no sn de js, o js ainda precisa ser chamado e acredito que, se estiver no cache, o navegador a utilizará a partir daí.
25712 Sean
2
A página de teste blog.kosny.com/testpages/safari-gz indica que o aviso "Cuidado para nomear e testar no Safari. Como o safari não suporta css.gz ou js.gz" está desatualizado. No Safari 7 no Mavericks e no Safari no iOS 7, o css.gz e o js.gz funcionam. Não sei quando essa alteração ocorreu, estou apenas testando com os dispositivos que tenho.
precisa
14

O Cloudfront suporta gzipping.

O Cloudfront se conecta ao seu servidor via HTTP 1.0. Por padrão, alguns servidores da web, incluindo nginx, não veiculam conteúdo compactado com gzip nas conexões HTTP 1.0, mas você pode solicitar isso adicionando:

gzip_http_version 1.0

à sua configuração nginx. A configuração equivalente pode ser definida para qualquer servidor Web que você estiver usando.

Isso tem um efeito colateral de fazer com que as conexões keep-alive não funcionem para conexões HTTP 1.0, mas como os benefícios da compactação são enormes, definitivamente vale a pena.

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

Editar

Exibir conteúdo compactado rapidamente na frente da nuvem da Amazon é perigoso e provavelmente não deve ser feito. Basicamente, se o servidor da Web estiver compactando o conteúdo com um gzip, ele não definirá um Comprimento de conteúdo e enviará os dados como agrupados.

Se a conexão entre o Cloudfront e seu servidor for interrompida e interrompida prematuramente, o Cloudfront ainda armazenará em cache o resultado parcial e servirá como a versão em cache até que expire.

A resposta aceita de compactar primeiro o disco no disco e depois veicular a versão compactada é uma idéia melhor, pois o Nginx poderá definir o cabeçalho Content-Length e, portanto, o Cloudfront descartará versões truncadas.

Danack
fonte
5
-1, esta resposta não tem nada a ver com a pergunta. Nginx! = S3 e Cloudfront
Jonathan
@ Danack, você teve muitos problemas com o Cloudfront armazenando arquivos semi-recuperados devido a esse problema? Estou tentando entender o quanto isso foi um problema para você na prática.
31516
1
@poshest Aconteceu. Havia muito pouco benefício em servir o gzip em tempo real (como o gzip é tão rápido no servidor de qualquer maneira), então eu o desliguei assim que vi acontecer. Dados corrompidos são um problema muito maior do que ter um "tempo até o primeiro byte" demorar 200 ms nos raros casos em que o conteúdo ainda não existe no formato compactado em gzip.
Danack 24/03
Se um ativo não possuir uma propriedade Comprimento de Conteúdo no cabeçalho, mas incluir Transfer-Encoding: chunked (como é o caso dos ativos compactados com gzip), o CloudFront NÃO armazenará em cache um ativo parcial se não receber um pedaço final. Se faltam essas duas propriedades, é possível que um recurso incompleto seja armazenado em cache. Veja: docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…
Cody Duval
5

Recentemente, fizemos algumas otimizações para o uSwitch.com para compactar alguns dos ativos estáticos em nosso site. Embora configuremos um proxy nginx inteiro para fazer isso, também montei um pequeno aplicativo Heroku que faz proxy entre o CloudFront e o S3 para compactar o conteúdo: http://dfl8.co

Como objetos S3 acessíveis ao público podem ser acessados ​​usando uma estrutura de URL simples, http://dfl8.co apenas usa a mesma estrutura. Ou seja, os seguintes URLs são equivalentes:

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

Ontem a amazon anunciou um novo recurso, agora você pode ativar o gzip na sua distribuição.

Ele funciona com s3 sem adicionar arquivos .gz, tentei o novo recurso hoje e funciona muito bem. (é necessário invalidar os objetos atuais)

Mais informações

Chris
fonte
0

Você pode configurar o CloudFront para compactar automaticamente arquivos de certos tipos e servir os arquivos compactados.

Consulte o Guia do desenvolvedor da AWS

Rafi
fonte
Você pode adicionar mais informações sobre sua solução (talvez um exemplo) para torná-la uma resposta melhor.
Yagami Light