Mais performance com jQuery e conteúdo carregado ao final da página

Estava lendo um ótimo artigo no 24 ways sobre aumentar a velocidade do site carregando as imagens após todo o carregamento do site. A primeira solução apresentada no artigo não havia me satisfeito, mas foi em um comentário que encontrei uma solução que podemos trabalhar em cima e apresentar algo mais interessante.

Vamos ao caso

Temos uma página onde carregamos conteúdo principal, com texto, css, js, imagens, plugins, etc. Também temos conteúdo que lá são carregados para conteúdo não principal, como alguns widgets externos (facebook, twitter, etc) e imagens (como o gravatar nos comentários).

Uma outra ideia é que não podemos perder a acessibilidade de nosso site, aquela história de alguém poder carregar o site sem javascript ou até quando se trata de um motor de busca.

Queremos carregar esse conteúdo não principal apenas após todo o principal ser carregado.

Vamos a prática:

Na nossa página vamos ter uma imagem que não faz parte do conteúdo principal:

<img src="http://mw2.google.com/mw-panoramio/photos/medium/38960181.jpg" width="500" height="375" alt="Praia" />

Vamos agora colocar ele para ser carregado apenas pra quem nao tem javascript sendo executado:

<noscript data-delayed>
  <img src="http://mw2.google.com/mw-panoramio/photos/medium/38960181.jpg" width="500" height="375" alt="Praia" />
</noscript>

Para quem ainda não conhece, o conteúdo da tag noscript é ignorado pelo navegador quando o javascript está habilitado.

Agora, com o jQuery, vamos buscar cada elemento noscript que contenha o atributo data-delayed.

jQuery('noscript').each( function() {
    console.log(typeof jQuery(this).data('delayed')); // string vazia
    console.log(typeof jQuery(this).data('nao_existe')); // undefined
});

Note que o atributo data-* (esse * pode ser uma palavra qualquer para identificar o dado a ser passado) é um atributo novo do HTML5, facilmente trabalhado com o jQuery pelo método .data('sufixo') e pode conter um valor.

Veja que quando há um atributo data existente, mas sem valor, o jQuery retorna uma string vazia e quando não há esse atributo data, ele retorna um valor não definido (undefined).

Todo elemento noscript com atributo data-delayed

Assim, podemos buscar todos os elementos noscript que contenham atributo data-delayed e aplicar seu conteúdo após o carregamento da página e seu conteúdo principal. Vamos utilizar o jQuery(window).load que vai garantir a execução dessa rotina após DOM e seus elementos estiverem totalmente carregados. Obs: o jQuery(document).ready aguarda apenas a estrutura do DOM estar carregada, não necessariamente os seus elementos, como as imagens.

jQuery(window).load( function() {
    $('noscript').each( function() {
        var $this = $(this);
        if ( typeof $this.data('delayed') === 'string' ) {
            $this.before( $this.text() );
            $this.remove();
        }
    });
});

Veja o pulo do gato

O conteúdo do 'noscript' é ignorado pelo navegador quando temos o javascript sendo executado, logo, não temos ali tags de fato. Quando puxamos o conteúdo do 'noscript' como html, as tags vão vir escapadas (> e <).

Assim, buscamos o conteúdo texto mesmo, e mandamos inserir ele antes de cada 'noscript' com o método .before() que aguarda um texto com conteúdo html.

Logo após, removemos o noscript da página, não vamos precisar mais da existência dele em nossa página após essa rotina.

Confira a execução

Coloquei um exemplo dessas rotinas no jsfiddle, de uma olhada: