Laboratorio: carga secciones de javascript de forma dinámica
Ayer fuà vÃctima de las librerÃas de Javascript, utilicé jQuery para facilitar el ajax y de paso para el DOM, cuando para esto último no hubiera sido necesario, tardé más en enterarme de cómo hacer un getElementById en jQuery que en hacerlo sin más.
Ante esto me pregunté si no serÃa mejor coger la librerÃa de jQuery y dividirla en funcionalidades, y cargar solo la parte que vayamos a usar. Para ello se me ocurrió transformar el .js en un .php y cargar las diferentes funcionalidades según unos parámetros de entrada. Veo que aNieto2K ha tenido una idea parecida y buenÃsima, pero mediante javascript. En el caso que yo comento se podrÃa hacer que si quiero Ajax, a parte también se carguen las funcionalidades del DOM que pueda usar la parte Ajax, transparente para el que use la librerÃa.
Para realizar esto, he tenido en cuenta dos cosas: obtener ciertos parámetros de entrada y según estos, cargar ciertas partes del script y usar un sencillo sistema de caché para no estar teniendo que crear en script online todo el tiempo.
Para el sistema de caché, crearemos un archivo js para cada combinacion de parámetros de entrada. Supongamos que el script se divide en cuatro funcionalidades: Ajax, efectos, css y DOM, por cada una de estas funcionalidades debemos enviar un parámetro de entrada (si no lo enviamos es como si dijéramos que no queremos esa funcionalidad), si el parámetro se ha enviado ponemos un flag a 1, y si no a 0. Por lo que si queremos ajax y css tendremos el siguiente flag 1010, lo que querrá decir que queremos ajax, no queremos efectos, queremos css y no queremos DOM. Usaremos este código para referenciar al script cache correspondiente, asÃ, por ejemplo, tendrÃamos el fichero libreria_1010.js.php que representa el cache con funcionalidades de ajax y de css.
A ese nombre de fichero le tenemos que añadir la fecha de modificación del script original, para poder comprobar que el script no ha sido modificado y asà no encontrarnos en la situación de que estamos tirando de una cache desactualizada. Tendremos al final un nombre de fichero de la siguiente manera: libreria_0110.1170856900.js.php.
Bien, ya tenemos la lógica de los nombres de fichero de los scripts, ahora solo nos falta comprobar si existe un fichero cache para las funcionalidades solicitadas para cualquier fecha. Si existe y la fecha es la misma que la del script original, leemos el fichero y lo devolvemos. Si no existe o el fichero es de una fecha distinta, creamos el fichero nuevo y borramos el anterior en caso de que existiera.
El código del script serÃa el siguiente, en este caso solamente saco un alert que muestra la funcionalidad solicitada para facilitar el entendimiento de toda la explicación.
<?php
$ajax = isset($_GET["ajax"])? "1" : "0";
$efectos = isset($_GET["efectos"])? "1" : "0";
$css = isset($_GET["css"])? "1" : "0";
$dom = isset($_GET["dom"])? "1" : "0";
// Empiezo el buffering
// Obtengo la fecha de este script
$fecha = filemtime($_SERVER["SCRIPT_FILENAME"]);
$existe_anterior = false;
$fichero_anterior = null;
// Busco si hay algun archivo de cache con un timestamp distinto al actual, para actualizar la cache
if ($dir = opendir('.')) {
while (false !== ($file = readdir($dir))) {
if (strpos($file, "libreria_$ajax$efectos$css$dom") == 0 &&
$file != "libreria_$ajax$efectos$css$dom_$fecha.js.php") {
$existe_anterior = true;
$fichero_anterior = $file;
}
}
closedir($dir);
}
$nombre_fichero = "libreria_$ajax$efectos$css$dom.$fecha.js.php";
if (file_exists($nombre_fichero) ∓∓ !$existe_anterior) {
$f = fopen($nombre_fichero, "r");
$contenido = fread($f, filesize($nombre_fichero));
fclose($f);
echo $contenido;
} else {
ob_start();
?>
<?php
if ($ajax) {
?>
alert('ajax');
<?php
}
?>
<?php
if ($efectos) {
?>
alert('efectos');
<?php
}
?>
<?php
if ($css) {
?>
alert('css');
<?php
}
?>
<?php
if ($dom) {
?>
alert('dom');
<?php
}
?>
<?php
// obtengo la salida
$salida = ob_get_contents();
ob_end_clean();
// borro el fichero anterior de la cache
unlink($fichero_anterior);
// guardo en fichero
$f = fopen($nombre_fichero, 'a');
fwrite($f, $salida);
fclose($f);
// devuelvo la salida
echo $salida;
}
?>
Empecé a hacerlo para jQuery, pero siendo sinceros, el código es algo lioso de seguir y se me han quitado las ganas, aún asÃ, invito a cualquiera que le sobren unas cuantas horas de tiempo libre para que lo haga.