Em produção, todos os seus arquivos Javascript, por exemplo, serão pré-compilados e no seu layout ele vai renderizar algo assim em produçao:
1 |
<script src="/assets/application-92d3fd2d9ebe06a3a45e1ee88109c64f.js" type="text/javascript"></script> |
Eu já escrevi sobre o Asset Pipeline, como usar o Rails Assets para consumir pacotes Bower sem o Bower. Anos atrás uma última coisa que eu fazia era enviar assets pré-compilados para o AWS S3 usando o Asset Sync, mas atualmente essa é a forma errada de fazer isso. Em vez disso vamos colocar tudo num CDN de verdade como o AWS CloudFront.
Um CDN como o CloudFront funciona da seguinte forma. Ao terminar a configuração que vou explicar abaixo, o HTML que carrega o Javascript acima vai ser renderizado da seguinte forma na sua aplicação:
1 |
<script src="https://d1g6lioiw8beil.cloudfront.net/assets/application-92d3fd2d9ebe06a3a45e1ee88109c64f.js" type="text/javascript"></script> |
Ou seja, ele vai pedir para esse subdomínio "d1g6lioiw8beil" no domínio do cloudfront.net. Ao não encontrar ele vai pedir ao domínio que você configurou. No meu caso, ele vai pedir para:
1 |
https://www.akitaonrails.com/assets/application-92d3fd2d9ebe06a3a45e1ee88109c64f.js |
Então ele fará o cache esse arquivo e qualquer nova requisição pelo mesmo arquivo vai devolver do cache do CloudFront e sua aplicação não vai mais receber nenhuma requisição por esse arquivo. O mesmo vai acontecer com todos os demais assets do site, incluindo os stylesheets e imagens.
Quando fizer uma atualização que muda os assets, o fingerprint/hash do arquivo vai mudar. Daí o ciclo reinicia: o CloudFront não vai ter, ele pede pra sua aplicação - que precisa servir o novo arquivo apenas uma vez - e uma vez gravado novamente no cache, sua aplicação não recebe mais nenhuma requisição do mesmo arquivo outra vez.
Se você usou corretamente helpers como image_tag, asset_path e associados, então já tem tudo que precisa. Sua aplicação já pré-compila os assets corretamente e mostra as URLs corretas com os devidos hashes de cada arquivo concatenado e minificado.
Melhor ainda, tecnicamente o CloudFront vai puxar o arquivo do servidor de cache mais próximo, geograficamente, de onde o usuário que pediu sua página estiver, melhorando a performance geral do seu site do ponto de vista do usuário final.
Como Configurar e Instalar
Com sua conta no AWS criado, vá até o console do CloudFront e já pode começar imediatamente criando uma nova distribuição:
Guarde o domain name aleatório e único que ele vai criar pra você sobre "Domain Name", você vai precisar disso depois. Ele é no formato [id do domínio].cloudfront.net.
Só tem duas coisas que você precisa configurar. O primeiro é o domínio correto da sua aplicação em produção e um ID qualquer:
A segunda coisa é um único Whitelist Header, adicionando o header "Origin":
Pronto, é só isso que você precisa fazer no CloudFront. Você vai perceber que ele vai ficar com um spinner rodando e você precisa esperar ele terminar. Ele está configurando todos os edges.
Só de fazer isso você já pode testar. Basta pegar uma URL de produção de um asset seu e trocar seu domínio (no meu caso, "www.akitaonrails.com") pelo Domain Name com o ID aleatório que falei acima (no meu caso, "d1g6lioiw8beil.cloudfront.net"). Ele vai fazer o processo que expliquei antes: puxar do seu site o arquivo, fazer o cache, e passar a servir do cache.
Se o teste funcionar, basta adicionar a seguinte linha no arquivo config/environments/production.rb:
1 |
config.action_controller.asset_host = 'https://d1g6lioiw8beil.cloudfront.net' # trocar esse domain pelo seu |
Obviamente, colocando o Domain Name da sua distribuição do CloudFront. Faça um novo deployment e pronto! O Heroku tem uma documentação com mais detalhes, este meu post é um resumo simples que qualquer site em Rails pode seguir imediatamente.
Por muito tempo, muitos criticaram o Asset Pipeline por causa dos bugs que as primeiras versões tinham, mas até hoje todos estão tentando resolver um problema que o ecossistema Rails já resolveu desde 2009. E adicionar um CDN ao seu site todo com esforço quase zero, é prova da versatilidade que já temos pré-instalado em toda aplicação Rails moderna.