Introdução ao Google Closure
Aprenda a usar a biblioteca JavaScript do Google para dinamizar suas páginas web
O Google possui um trio de tecnologias de código aberto destinado a desenvolvedores que escrevem aplicações JavaScript em grande escala. Incluído no primeiro release estavam o Closure Compiler, um sofisticado compilador JavaScript, o Closure Library, uma enorme biblioteca de código JavaScript projetada para uso com o referido compilador, e o Closure Templates, um sistema de templates implementado em JavaScript e Java.
Essa é a tecnologia que tem alimentado as features do Gmail e vários outros aplicativos de alto perfil do Google (Google Docs, Reader, Calendário, Maps, entre outros). O Google designou que essa seria sua biblioteca padrão para aplicativos baseados em JavaScript. O Closure Tools, por sua vez, é uma biblioteca que foi projetada com objetivos diferentes dos de outras bibliotecas populares, como o jQuery e o Prototype.js.
Para pequenas aplicações, blogs, galerias de design ou sites de conteúdo estático que só precisam de alguma validação de formulário simples, o Closure é provavelmente um exagero. Ele é comumente associado a soluções dinâmicas, como o Closure Compiler, que permite uma pegada eficiente para aplicações de qualquer tamanho e escalabilidade. No entanto, a curva de aprendizagem é bastante íngreme, há muito menos exemplos e você precisa encontrar uma maneira de integrar o compilador em seu fluxo de trabalho. Com uma biblioteca como o jQuery, basta adicionar uma referência de script (se estiver usando um CDN, por exemplo, não é necessário sequer fazer o download físico do arquivo) e iniciar a codificação à distância.
Portanto, além das grandes aplicações web do Google, o Closure serve para quê? Ele é uma excelente opção a se considerar para qualquer aplicação de tamanho médio e grande, independentemente do nicho de tecnologias usadas no back-end da mesma. Essas aplicações quase sempre envolvem vários desenvolvedores e são suscetíveis de conter pelo menos 100kbytes de código fonte quando referentes a bibliotecas de terceiros. Se não houver um sistema de build estabelecido para combinar os scripts, uma página média de uma aplicação desse tamanho provavelmente faz referência de 5 a 10 scripts externos, se não mais.
Se o seu aplicativo alcançou esse nível de complexidade (ou você tenha projetado para alcançá-lo), este é um bom ponto de partida, onde os benefícios do Closure começam a se tornar significativos. O impacto do Closure Compiler na velocidade da execução do seu código e tamanho será significativo, e é provável que você esteja em posição de se beneficiar de uma grande parcela da Closure Library também. Vamos dar uma olhada nos dois principais componentes do Closure Tools.
Closure Compiler
O Closure Compiler é sem dúvida o componente principal do Closure Tools. Ele suporta dois modos de otimização primária: a “minificação” (onde o conteúdo inteiro do arquivo é posto em uma só linha) e a “compilação avançada”.
Os minificadores JavaScript não são algo novo na comunidade de desenvolvimento. Um compilador JavaScript sequer é necessariamente algo novo também, assim como os compiladores de outras linguagens também têm abordado por algum tempo essa questão de compilar seus códigos nativamente. O que é único sobre o Closure Compiler é que é um compilador JavaScript-to-JavaScript capaz de realizar otimizações de código que antes eram desconhecidas e impossíveis de serem feitas com ferramentas convencionais. O Closure Compiler pode ser usado como um componente independente em uma base de código JavaScript existente, ou em conjunto com a Closure Library, que foi concebida para uma máxima otimização quando usada com o compilador. É mais fácil entender o poder desses recursos avançados de compilação por meio de um exemplo simples. Considere o script da Listagem 1.
Listagem 1. Exemplo de script simples no Closure.
function naoUsado() {
alert('sou chamado apenas após uma função não chamada');
}
function naoUsado2() {
naoUsado();
alert('nunca sou chamado');
}
function ola(nome) {
alert('Ola, ' + nome + '!');
}
var oi = ola;
oi('amigo');
Após a execução desse pedaço de código via compilador no modo avançado, ficaremos com o seguinte trecho de código gerado:
alert("Ola, amigo!");
O compilador elimina o código morto, funções inline, otimiza a concatenação e nos deixa com um resultado significativamente menor, mas funcionalmente idêntico.
Pode parecer estranho ou arbitrário que nesses exemplos as funções não utilizadas simplesmente desapareceram na saída. O compilador considera essa remoção perfeitamente segura e razoável porque ele assume que você tenha fornecido todo o código fonte da sua aplicação. Se você quer que uma de suas funções esteja disponível fora do contexto da tag <script> em seu código JavaScript, você precisa dizer explicitamente ao compilador para exportá-la.
Isso não quer dizer que não haverá quaisquer chamadas de função em sua compilação final, caso não exporte nada. O Closure Compiler só usa código embutido quando o considera adequado. Quando não estão inlining, as funções normalmente serão renomeadas. Se o compilador escolheu não trabalhar de forma inline com a nossa função ola, por exemplo, a saída seria algo parecido com o seguinte:
function a(b){alert("Ola, "+b+"!")}a("amigo");
Veja como o código foi minificado conforme dissemos. Se a sua reação ao código apresentado é de espanto, você provavelmente não é o único. Qualquer um que tenha escrito grandes sistemas em JavaScript sabe que a depuração do código é uma parte inevitável do processo. As otimizações significativas fornecidas pelo Closure Compiler podem ajudar a tornar seu código menor, porém também tornam um pouco difícil o mapeamento de volta para o código original. Caso ocorra uma falha de tempo de execução que só acontece no código compilado, o que fazer?
Felizmente, o Closure Compiler é capaz de criar um mapa de origem, o que permite que áreas do código compilado possam ser definitivamente rastreadas até a fonte original. Você não tem que trabalhar com o próprio arquivo no mapa de origem, pois o Google fornece o Closure Inspector, uma extensão do Firebug (famoso plugin de depuração JavaScript para Firefox), que se integra à sua experiência de depuração padrão.
Enquanto o Closure Compiler é uma excelente ferramenta para otimizar o tamanho do código e a velocidade de execução, esse não é o único valor que ele proporciona. Ele também suporta grandes números de anotações JSDoc, que lhe permite ajudar a encontrar erros em seu código. Por exemplo, poderíamos redefinir a nossa função ola com um tipo de anotação, usando o código de igual forma ao demonstrado na Listagem 2.
Listagem 2. Anotando nossa função de ola().
/** @param nome */
function ola(nome) {
alert(Ola, ' + nome + '!');
}
Aqui dizemos que o compilador terá um único parâmetro do tipo string. Agora, vamos adicionar algumas chamadas problemáticas à função:
ola();
ola(3.14);
Ademais, quando compilarmos esse código, o compilador emitirá os avisos demonstrados na Listagem 3.
Listagem 3. Avisos do compilador do Closure após execuções problemáticas.
JSC_WRONG_ARGUMENT_COUNT: Function ola: called with 0 argument(s).
Function requires at least 1 argument(s) and no more than 1 argument(s).
at line 5 character 5
ola();
^
JSC_TYPE_MISMATCH: actual parameter 1 of ola does not match formal parameter
found : number
required: string at line 6 character 6
Com grandes programas em particular, esses avisos podem ajudar a isolar dificuldades rapidamente e encontrar erros que de outra forma só seriam visíveis em tempo de execução. As únicas desvantagens são as necessidades de adicionar as tags do JSDocs a seus comentários de código e a necessidade de realizar “casts” de vez em quando, como no trecho a seguir:
// "cast" explícito de um para um
var element = /** @type */ (node);
goog.dom.setTextContent(element, 'successo!');
Closure Library
A Closure Library é uma biblioteca enorme de código JavaScript otimizado para o uso com o Closure Compiler. Em teoria, o emparelhamento com o Compiler é opcional. E, de fato, essa é uma característica extremamente importante em ambientes de desenvolvimento, uma vez que torna a etapa de compilação opcional e acelera drasticamente alguns estágios de desenvolvimento. No ambiente de produção, no entanto, o uso do compilador não é opcional, pois o código não compilado da biblioteca é muito grande, e a estratégia utilizada para incluir os arquivos não foi projetada para ser eficiente.
O código do Closure Library é atualizado periodicamente em um repositório de subversão pública, que é alimentado a partir do sistema de controle da origem interna do Google. Isso não significa que a qualidade é de “pré-lançamento” (ou “beta”), simplesmente significa que o Google está confiante o suficiente para lançar versões mais estáveis. Muitas partes da Closure Library estão ativamente em produção no Google, e ela vem com um conjunto enorme de testes de unidade. No fim, cabe a você ou sua organização determinar se ela é estável o suficiente para suas necessidades.
Então o que está lá dentro, ocupando todo esse espaço? A maior parte são os comentários. O Closure Library é exaustivamente documentado e a maioria da sua documentação está dentro do próprio código. Isso torna a navegação do código uma grande estratégia para aprender mais sobre o Closure. Uma parte da biblioteca é dedicada a fatores que seriam de grande utilidade em qualquer projeto JavaScript, incluindo aqueles que não tem como alvo os navegadores web (Array, crypt, date, math, string e muito mais). A porção maior do código é projetada exclusivamente para aplicações JavaScript visando os navegadores (dom, editor, fx, history, style, ui, useragent e outros). Um bom ponto de partida para compreender o que está disponível no Closure Library é a pasta demos (index), onde você encontrará exemplos de implementações tão básicas como a manipulação de eventos e tão exóticas como um pop-up de figuras “emoji”. Por último, a Closure Library também inclui o código de terceiros selecionados.
O código da Closure Library é modular, com o respectivo código organizado em “namespaces” (que nada mais são que objetos com ou sem propriedades que usamos para evitar conflitos de variáveis ao associar as mesmas a um namespace). Essa organização é bem adequada para projetos de grande dimensão, com grandes equipes. Outra vantagem dessa estratégia é que o namespacing da Closure Library foi feito de modo a raramente interferir com as bibliotecas existentes, uma vez que todo o código da biblioteca está organizado sob um símbolo global único (goog). Note que isso não significa necessariamente que outras bibliotecas não terão impacto sobre o comportamento da Closure Library. Existem bibliotecas que poluem o espaço global de forma imprevisível, ou modificam os protótipos dos tipos built-in JavaScript para obter um código da Closure Library que se comportará indevidamente (como faria qualquer outra biblioteca de terceiros). Em outras palavras, a Closure Library não trará problemas a implementações de terceiros desde que elas também não interfiram em seu fluxo de execução convencional.
A desvantagem em relação à estratégia de namespacing é que seu código acaba sendo mais detalhado. Há muitas maneiras de controlar isso. Você pode decidir que a sua aplicação não precisará interoperar com outras bibliotecas e pode adicionar segurança através do uso dos alias para as funções comumente usadas no espaço de nomes globais. Por exemplo, se o trecho de código goog.dom.getElement parece muito grande para o que você está acostumado a escrever de código, você pode seletivamente trocar o namespacing simplesmente adicionando um alias global, como $:
goog.exportSymbol('$', goog.dom.getElement);
Há, é claro, riscos ao modificar o namespace global dessa forma, por isso é, sem dúvida, uma coisa boa o fato de os designers da Closure Library terem deixado essa decisão a cargo dos próprios desenvolvedores que, por sua vez, assumirão os riscos de tal implementação abstendo a biblioteca desse papel."
[...] continue lendo...Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo