Comprimir archivos con la API de Closure Compiler Service

El servicio de compilador para cierres está obsoleto y se quitará. En su lugar, considera ejecutar el compilador de forma local.

Descripción general

En Comunicación con la API, se describen los aspectos básicos para comunicarse con el servicio de Closure Compiler, pero solo se ilustra el uso del servicio con el propósito de quitar comentarios de una sola línea de JavaScript. En este instructivo, se ilustra cómo usar el servicio de Closure Compiler en una situación de desarrollo más realista: procesar todo un archivo de JavaScript a fin de lograr una reducción significativa de tamaño.

En este instructivo, se supone que tienes conocimientos básicos de JavaScript y HTTP. Si bien usa una secuencia de comandos de Python para enviar JavaScript al servicio de Closure Compiler, no necesitas saber Python para seguir el ejemplo.

  1. Cómo comprimir un archivo
  2. Mejora la compresión
    1. ¿Cuánto más pequeño es el código?
    2. ¿Qué hizo el servicio de Closure Compiler para reducir el tamaño del programa?
  3. Próximos pasos

Cómo comprimir un archivo

En el ejemplo de Comunicación con la API, se pasa una string de JavaScript como un parámetro de línea de comandos a nuestra secuencia de comandos de compilación. Sin embargo, este enfoque no funcionará muy bien para un programa de JavaScript de tamaño realista, ya que la string de JavaScript se vuelve difícil de manejar cuando el código supera unas pocas líneas. En el caso de los programas más grandes, puedes usar el parámetro de solicitud code_url para especificar el nombre del archivo JavaScript que quieres procesar. Puedes usar code_url además de js_code, o como reemplazo de js_code.

Por ejemplo, considera el siguiente programa de JavaScript:

/**
 * A simple script for adding a list of notes to a page. The list diplays
 * the text of each note under its title.
 */

/**
 * Creates the DOM structure for a note and adds it to the document.
 */
function makeNoteDom(noteTitle, noteContent, noteContainer) {
  // Create DOM structure to represent the note.
  var headerElement = document.createElement('div');
  var headerText = document.createTextNode(noteTitle);
  headerElement.appendChild(headerText);

  var contentElement = document.createElement('div');
  var contentText = document.createTextNode(noteContent);
  contentElement.appendChild(contentText);

  var newNote = document.createElement('div');
  newNote.appendChild(headerElement);
  newNote.appendChild(contentElement);

  // Add the note's DOM structure to the document.
  noteContainer.appendChild(newNote);
}

/**
 * Iterates over a list of note data objects and creates a DOM
 */
function makeNotes(data, noteContainer) {
  for (var i = 0; i < data.length; i++) {
    makeNoteDom(data[i].title, data[i].content, noteContainer);
  }
}

function main() {
  var noteData = [
      {title: 'Note 1', content: 'Content of Note 1'},
      {title: 'Note 2', content: 'Content of Note 2'}];
  var noteListElement = document.getElementById('notes');
  makeNotes(noteData, noteListElement);
}

main();

Puedes pasar este programa al servicio de Closure Compiler de forma más conveniente como un archivo que como una string grande. Sigue estos pasos para procesar un archivo con el servicio:

  1. Guarda el código JavaScript en un archivo.
  2. Haz que el archivo sea accesible en la Web (por ejemplo, súbelo a tu servidor web).
  3. Realiza una solicitud POST al servicio de Closure Compiler como se muestra en Comunicación con la API, pero para el parámetro js_code sustituye un parámetro code_url. El valor de code_url debe ser la URL del archivo JavaScript que se creó en el Paso 1.

Por ejemplo, puedes encontrar el código JavaScript de este ejemplo en el archivo tutorial2.js. Para procesar este archivo con la API de servicio de Closure Compiler, cambia el programa Python de Comunicación con la API a fin de usar code_url, de la siguiente manera:

#!/usr/bin/python2.4

import httplib, urllib, sys

# Define the parameters for the POST request and encode them in
# a URL-safe format.

params = urllib.urlencode([
    ('code_url', sys.argv[1]), # <--- This parameter has a new name!
    ('compilation_level', 'WHITESPACE_ONLY'),
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

# Always use the following value for the Content-type header.
headers = { "Content-type": "application/x-www-form-urlencoded" }
conn = httplib.HTTPSConnection('closure-compiler.appspot.com')
conn.request('POST', '/compile', params, headers)
response = conn.getresponse()
data = response.read()
print data
conn.close()

Nota: Para reproducir este ejemplo, es posible que los usuarios de Windows deban instalar Python. Consulta las Preguntas frecuentes de Windows Python para obtener instrucciones sobre cómo instalar y usar Python en Windows.

Envía el código al servicio de Closure Compiler con el siguiente comando:

$ python compile.py https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js

El servicio de Closure Compiler recupera el archivo de https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js y muestra JavaScript comprimido en la respuesta.

Para compilar varios archivos de salida juntos en un archivo de salida, incluye varios parámetros code_url, como en este ejemplo:

params = urllib.urlencode([
    # Multiple code_url parameters:
    ('code_url', 'http://yourserver.com/yourJsPart1.js'),
    ('code_url', 'http://yourserver.com/yourJsPart2.js'),
    ('compilation_level', 'WHITESPACE_ONLY'),
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

Cómo mejorar la compresión

En los ejemplos hasta ahora, se usó un compilation_level de WHITESPACE_ONLY, que solo quita los comentarios y el espacio en blanco. Con el nivel de compresión SIMPLE_OPTIMIZATIONS, puedes lograr tasas de compresión mucho más altas. Para usar la compresión SIMPLE_OPTIMIZATIONS, cambia el parámetro compilation_level a SIMPLE_OPTIMIZATIONS:

params = urllib.urlencode([
    ('code_url', sys.argv[1]),
    ('compilation_level', 'SIMPLE_OPTIMIZATIONS'),  # <--- This parameter has a new value!
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

y ejecutar la secuencia de comandos como antes:

$ python compile.py https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js

El resultado debería verse así:

var GLOBAL_document=document,$$PROP_appendChild="appendChild";function makeNoteDom(a,b,c){var d=GLOBAL_document.createElement("div");a=GLOBAL_document.createTextNode(a);d[$$PROP_appendChild](a);a=GLOBAL_document.createElement("div");b=GLOBAL_document.createTextNode(b);a[$$PROP_appendChild](b);b=GLOBAL_document.createElement("div");b[$$PROP_appendChild](d);b[$$PROP_appendChild](a);c[$$PROP_appendChild](b)}function makeNotes(a,b){for(var c=0;c<a.length;c++)makeNoteDom(a[c].title,a[c].content,b)}
function main(){var a=[{title:"Note 1",content:"Content of Note 1"},{title:"Note 2",content:"Content of Note 2"}],b=GLOBAL_document.getElementById("notes");makeNotes(a,b)}main();

Este código es más difícil de leer que el programa de origen, pero es más pequeño.

¿Cuánto más pequeño es el código?

Si cambiamos output_info en nuestros parámetros de solicitud de compiled_code a statistics, podremos ver exactamente cuánto espacio ahorramos:

Original Size: 1372
Compressed Size: 677
Compilation Time: 0

El nuevo JavaScript es menos de la mitad del tamaño del original.

¿De qué manera el servicio de compilación de cierres hizo que el programa fuera más pequeño?

En este caso, Closure Compiler logra la reducción de tamaño en parte mediante el cambio del nombre de las variables locales. Por ejemplo, el archivo original incluye esta línea de código:

var headerElement = document.createElement('div');

Closure Compiler cambia esta instrucción por:

var d=document.createElement("div");

Closure Compiler cambia el símbolo headerElement a d en todas partes dentro de la función makeNoteDom y, por lo tanto, conserva la funcionalidad. Sin embargo, los 13 caracteres de headerElement se acortaron a un carácter en cada uno de los tres lugares donde aparecen. Esto permite ahorrar 36 caracteres en total.

La compilación con SIMPLE_OPTIMIZATIONS siempre conserva la funcionalidad de JavaScript válido sintácticamente, siempre que el código no acceda a variables locales mediante nombres de string (por ejemplo, declaraciones eval()).

Próximos pasos

Ahora que estás familiarizado con SIMPLE_OPTIMIZATIONS y con la mecánica básica de usar el servicio, el siguiente paso es aprender sobre el nivel de compilación de ADVANCED_OPTIMIZATIONS. Este nivel requiere algunos pasos adicionales para garantizar que JavaScript funcione de la misma manera antes y después de la compilación, pero reduce el tamaño de JavaScript. Consulta Compilación y elementos externos avanzados para obtener más información sobre ADVANCED_OPTIMIZATIONS.