Minimizar/comprimir archivos JS y CSS



Descarga: comprimir-css-y-js.zip (incluye YUI Compressor 2.4.8 y el script de Python).

Al momento de desarrollar aplicaciones web, vía CGI o WSGI, con Django, web2py, Pyramid o cualquiera fuese la librería, incluso páginas estáticas o en otros lenguajes de programación, comprimir archivos estáticos o que no cambian muy a menudo su contenido es una buena práctica para acelerar el tiempo de carga tu web y mejorar la experiencia del usuario. En el caso de archivos de JavaScript y CSS, “comprimir” o “minimizar” es, principalmente, remover comentarios y eliminar saltos de línea y espacios en blanco innecesarios. Para el caso de JavaScript en particular, algunos compresores también incluyen optimización y ofuscación del código.

En este artículo estaremos utilizando YUI Compressor, un programa escrito en Java para comprimir archivos de JavaScript y CSS. Puedes descargarlo desde este enlace, y la máquina virtual de Java (necesaria para ejecutarlo) desde aquí. En la página encontrarás todas las opciones disponibles, pero básicamente funciona con el siguiente comando.

java -jar yuicompressor-2.4.8.jar -o styles.min.css styles.css

En donde styles.min.css es el nombre del archivo de salida (que será creado automáticamente) y styles.css el archivo de entrada (aquél que queremos comprimir). YUI Compressor detecta el tipo de archivo (JavaScript o CSS) en base a la extensión del nombre del fichero (.js o .css).

(Nota: si estás usando otra versión de YUI Compressor, recuerda indicar correctamente el nombre del archivo .jar; al momento en que escribo este artículo la última versión disponible es 2.4.8.)

Veamos un ejemplo. Considerando el siguiente archivo chat.js:

var ws;
var username;

function onKeyUp(event)
{
    if (event.keyCode == 13)
        sendMessage();
}

function sendMessage()
{
    message = document.getElementById("message");
    if (message.value)
    {
        ws.send("<strong>" + username + "</strong>: " + message.value);
        message.value = "";
    }
    message.focus();
}

function checkSupport()
{
    if (!("WebSocket" in window))
    {
        document.getElementById("login").innerHTML = "Este navegador no soporta WebSockets.";
    }
}

function loadChat()
{
    username = document.getElementById("username").value;
    if (!username)
        return;

    document.getElementById("login").hidden = true;
    document.getElementById("chat").hidden = false;

    messages = document.getElementById("messages");
    messages.innerHTML = "";

    ws = new WebSocket("ws://localhost:9998");

    ws.onopen = function()
    {
        ws.send(username + " ha ingresado al chat.");
    };

    ws.onclose = function()
    {
        chat.innerHTML = "Se ha perdido la conexión."
    };

    ws.onmessage = function(evt) 
    { 
        messages.innerHTML += evt.data + "<br />";
        messages.scrollTop = messages.scrollHeight;
    };
}

function closeChat()
{
    ws.send(username + " se ha desconectado.");
    ws.close();
}

Ejecutamos YUI Compressor:

java -jar yuicompressor-2.4.8.jar -o chat.min.js chat.js

Y el resultado en el archivo chat.min.js es el siguiente:

var ws;var username;function onKeyUp(a){if(a.keyCode==13){sendMessage()}}function sendMessage(){message=document.getElementById("message");if(message.value){ws.send("<strong>"+username+"</strong>: "+message.value);message.value=""}message.focus()}function checkSupport(){if(!("WebSocket" in window)){document.getElementById("login").innerHTML="Este navegador no soporta WebSockets."}}function loadChat(){username=document.getElementById("username").value;if(!username){return}document.getElementById("login").hidden=true;document.getElementById("chat").hidden=false;messages=document.getElementById("messages");messages.innerHTML="";ws=new WebSocket("ws://localhost:9998");ws.onopen=function(){ws.send(username+" ha ingresado al chat.")};ws.onclose=function(){chat.innerHTML="Se ha perdido la conexión."};ws.onmessage=function(a){messages.innerHTML+=a.data+"<br />";messages.scrollTop=messages.scrollHeight}}function closeChat(){ws.send(username+" se ha desconectado.");ws.close()};

Ahora bien, en lugar de ejecutar un comando por cada archivo de JavaScript o CSS que dispongas en tu aplicación o página web, puedes utilizar el siguiente script que comprime cada uno de ellos dentro de una determinada carpeta. Es decir, busca archivos con extensión .js y .css en las carpetas especificadas y excluye aquellos que finalicen en .min.js y .min.css.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from os import listdir
import subprocess


def main():
    # Carpetas en donde se encuentran los archivos
    # de JavaScript y CSS.
    paths = {"js": "static/js/",
             "css": "static/css/"}
    
    def get_files(path, ext):
        return (f for f in listdir(path)
                if f.endswith("." + ext) and
                not f.endswith(".min." + ext))
    
    def compress_file(path, filename, ext):
        print("Compressing {}...".format(filename))
        output_file = "{}{}.min.{}".format(
            path, filename[:-len(ext) - 1], ext)
        cmd = "java -jar yuicompressor-2.4.8.jar -o {} {}".format(
            output_file, path + filename)
        subprocess.call(cmd)
        print("Done.")
    
    for ext, path in paths.items():
        files = get_files(path, ext)
        for filename in files:
            compress_file(path, filename, ext)


if __name__ == "__main__":
    main()

Nótese que este script debe ubicarse junto con YUI Compressor. El script corre en Python 2.x y 3.x, pero Python 2 no acepta rutas relativas (debe especificarse la ruta completa de las carpetas JS y CSS).



Deja un comentario