Por que eu devo ler este artigo:Este artigo é útil por apresentar uma série de conceitos importantes acerca da biblioteca cross-browser JavaScript do Google para lidar com a manipulação do DOM, estruturas de dados e muito mais. Você aprenderá seus principais recursos através de uma implementação que leva em consideração o consumo dos serviços hospedados publicamente nos serviços do Yahoo Open Data Tables, o qual fornece várias APIs reais para consulta pública via linguagem de query própria. Ao final, você também estará apto a configurar seu ambiente, dar os primeiros passos e começar a se aventurar no universo do Google Closure por si só.

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 {string} 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 {Node} para um {Element}
  var element = /** @type {Element} */ (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.

Closure Library vs jQuery e Prototype

Então, se não modificarmos o namespace global, como o código da Closure Library se parece? A seguir veremos alguns exemplos de código simples comparando a sintaxe da Closure Library com duas outras bibliotecas populares: o jQuery e o Prototype.js. Os exemplos são funcionalmente equivalentes. Vejamos a primeira comparação na Listagem 4.

Listagem 4. Comparação # 1: Obter um único elemento por ID

jQuery
  var titulo = $("#titulo").get(0);
  // - or -
  var titulo = $("#titulo")[0];
   
  Prototype
  var titulo = $("titulo");
   
  Closure Library
  var titulo = goog.dom.getElement("titulo");
...

Quer ler esse conteúdo completo? Tenha acesso completo