Tratamento de arquivos Javascript grandes com turbolinks

Apesar de ter sido lançado há quase 2 anos, e ser automaticamente incluído no Rails desde 4.0.0, Turbolinks ainda parece causar uma boa quantidade de polêmica e debate sempre que é mencionado. Caramba, até mesmo os membros do Rails Core Team parecem discordar sobre o assunto:

<blockquote class = “twitter-tweet” lang = “en”>

“Se eu pudesse remover algo do Rails … hm … deixe-me pensar em algo menos óbvio do que TurboLinks” – <a href=” https://twitter.com/tenderlove”> @tenderlove </a> </p> – tone phreak ( @jacobian ) <a href=” https://twitter.com/jacobian/statuses/393752420792410112″> 25 de outubro de 2013 </a> </blockquote>
<script async src = “// platform.twitter. com / widgets.js “charset =” utf-8 “> </script>

Pessoalmente, acho que o Turbolinks é ótimo. Consideramos construir Screendoor como um aplicativo Javascript de página única, mas no futuro próximo, estamos mais felizes com a renderização do lado do servidor antigo + Turbolinks no topo, o que nos permite atingir um nível decente de desempenho sem ir API full-out + MVC do lado do cliente para nossos aplicativos, o que para uma loja do nosso tamanho seria um trabalho pesado.

Um obstáculo que começamos a atingir recentemente foi com o tamanho do nosso Javascript compilado – veja, uma vez que os Turbolinks apenas substituem o <body>do documento, é recomendado concatenar e minimizar o Javascript para todo o seu aplicativo (aparentemente usando o Rails Asset Pipeline) em um .jsarquivo grande e volumoso que só precisará ser carregado uma vez. No entanto, esse arquivo pode ficar grande rapidamente. Tipo, muito grande. Quando percebi que estávamos servindo mais de 400kb de Javascript, decidi que, embora esse arquivo fosse pulado no carregamento de uma página do Turbolinks, carregar meio megabyte de Javascript para usuários iniciantes e / ou sem cache devia ser muito trabalhoso .

Qual é a solução?

O método antigo de corrigir esse problema seria dividir seu Javascript em vários arquivos e incluí-los condicionalmente com base em onde são necessários. Portanto, para uma página com um editor WYSIWYG, você incluiria o script e poderia omitir aquela bola gigante de merda nas páginas sem. No entanto, com Turbolinks, qualquer tag adicional no cabeçalho acionará um recarregamento completo da página. Então está fora.wysiwyg.js<script>

Outra ideia seria simplesmente carregar o script de forma assíncrona via . Então, em vez de:$.getScript

$('textarea').wysiwyg()

Você obtém:

$.getScript('wysiwyg.js', function(){
$
('textarea').wysiwyg()
});

Mas ao carregar a página novamente, você acabará solicitando (e executando) o mesmo Javascript novamente. Nada de bom.

Minha solução? Algo que eu bati requireOnce. Ele aproveita o estado persistente do Javascript para armazenar uma matriz de scripts que foram carregados e, se um script já tiver sido carregado, ele simplesmente chama o retorno de chamada imediatamente. Aqui está em toda a sua glória:

(function(){
var requiredScripts = [];

window
.requireOnce = function (path, cb) {
if ($.inArray(path, requiredScripts) == -1) {
requiredScripts
.push(path)
$
.getScript(path, cb)
} else {
cb
()
}
}
})();

Use-o assim:

requireOnce('wysiwyg.js', function(){
$
('textarea').wysiwyg()
});

Estou curioso para saber o que todos pensam e como outras pessoas lidaram com isso no passado. Turbolinks podem ser complicados, mas com alguns truques como este na manga, parece que funciona bem.