Cómo utilizar el CDN gratuito de jsdelivr para cargar automáticamente y reemplazar las rutas de imágenes locales mediante un script

Sabemos que en un entorno de producción, almacenar imágenes en un CDN (Red de Distribución de Contenidos) puede acelerar la velocidad de carga y mejorar la experiencia del usuario. Recientemente me encontré con una necesidad similar: en un proyecto se referencian imágenes locales, supongamos que están en /images/xxx.{jpg,jpeg,png,gif} para facilitar el desarrollo local. Una vez finalizado el desarrollo, se comprimen todas las imágenes en el directorio images y se trasladan a /project/resources/images (resources es un proyecto git), se cargan automáticamente en GitHub mediante git, y luego se busca y reemplaza la ruta de las imágenes referenciadas en el proyecto local por la ruta del CDN. Entendiendo todo este proceso, podemos automatizarlo mediante un script. Primero, entendamos cómo jsdelivr implementa el CDN:

Relación entre jsdelivr CDN y GitHub

jsdelivr es un servicio gratuito y confiable de Red de Distribución de Contenidos (CDN) que permite a los desarrolladores almacenar recursos estáticos en un repositorio de GitHub y acceder a ellos globalmente mediante jsdelivr. Específicamente, jsdelivr puede proporcionar una URL de CDN para acelerar los recursos almacenados en el repositorio de GitHub, permitiendo que estos recursos se carguen rápidamente a nivel mundial.

Cómo asociar un proyecto de GitHub con jsdelivr

  1. Cargar los recursos en el repositorio de GitHub
    Primero, los desarrolladores deben cargar los recursos estáticos (como imágenes, archivos JavaScript, archivos CSS, etc.) en un directorio específico del repositorio de GitHub. Por ejemplo, podrías tener un repositorio en GitHub llamado my-project con una carpeta images que contiene algunas imágenes.

  2. Acceder a los recursos utilizando jsdelivr CDN
    Una vez que los recursos están cargados en el repositorio de GitHub, puedes acceder a ellos mediante la URL proporcionada por jsdelivr. jsdelivr proporciona una dirección CDN asociada al proyecto de GitHub que sigue este formato:

    1
    https://cdn.jsdelivr.net/gh/[NombreDeUsuarioGitHub]/[NombreDelRepositorio]@[EtiquetaORama]/[RutaDelArchivo]
    • [NombreDeUsuarioGitHub]: tu nombre de usuario en GitHub.
    • [NombreDelRepositorio]: el nombre del repositorio de GitHub donde están los recursos.
    • [EtiquetaORama]: la etiqueta o rama que quieres usar (por ejemplo, main o v1.0).
    • [RutaDelArchivo]: la ruta del recurso en el repositorio.

    Ejemplo:

    Supongamos que tu nombre de usuario en GitHub es johnsmith, el nombre de tu repositorio es my-project, y en la rama main tienes una carpeta images que contiene una imagen llamada logo.png. Puedes acceder a esta imagen mediante la siguiente URL de jsdelivr CDN:

    1
    https://cdn.jsdelivr.net/gh/johnsmith/my-project@main/images/logo.png

    En tu página web, puedes utilizar esta URL para referenciar la imagen, y jsdelivr acelerará la carga de esta imagen a nivel mundial, mejorando la velocidad de carga.

  3. Sincronización automática de actualizaciones
    Cuando actualizas los recursos en el repositorio de GitHub, jsdelivr automáticamente extrae los recursos más recientes, asegurándose de que el CDN tenga los recursos actualizados. Esto significa que cada vez que cargas una nueva versión de los recursos en el repositorio de GitHub, la URL de jsdelivr se actualizará automáticamente para proporcionar los archivos más recientes.

De esta manera, los desarrolladores pueden aprovechar la red de distribución global de jsdelivr CDN para acelerar la carga de los recursos estáticos almacenados en el repositorio de GitHub, mejorando la experiencia del usuario.

Pasos para la implementación

1. Instalar dependencias

Terminal window
1
pnpm add sharp fs-extra globby simple-git replace-in-file;

2. Comprimir y mover las imágenes

Primero, utilizamos la librería sharp para comprimir las imágenes, manteniendo la estructura de carpetas y trasladando las imágenes al directorio objetivo. Aquí está el código:

1
import { promises as fs } from "fs";
2
import path from "path";
3
import sharp from "sharp";
4
import fse from "fs-extra";
5
import { globby } from "globby";
6
7
const imagesDir = "/project/myproject/public/images";
8
const targetDir = "/project/resources/images";
9
10
async function compressAndCopyImages(srcDir, destDir) {
11
try {
12
const sourDir = `${srcDir}/**/*.{jpg,jpeg,png,gif}`;
13
await fse.ensureDir(destDir);
14
const entries = await globby([sourDir], { onlyFiles: false });
15
16
for (const entry of entries) {
17
const relativePath = path.relative(srcDir, entry);
18
const destPath = path.join(destDir, relativePath);
19
20
if ((await fs.stat(entry)).isDirectory()) {
21
await fse.ensureDir(destPath);
22
} else {
23
const metadata = await sharp(entry).metadata();
24
25
let options = {};
26
let formatOptions = {};
27
28
switch (metadata.format) {
29
case "gif":
30
options = { animated: true, limitInputPixels: false };
31
formatOptions = { colours: 128 };
32
break;
33
default:
34
formatOptions = { quality: 75 };
35
}
36
37
if (metadata.size < 10000) {
38
await fse.copy(entry, destPath);
39
console.log(`Copied ${relativePath} without compression`);
40
} else {
41
const dirPath = path.dirname(destPath);
42
await fse.ensureDir(dirPath);
43
await sharp(entry)?.[metadata.format](formatOptions).toFile(destPath);
44
console.log(`Compressed and copied ${relativePath}`);
45
}
46
}
47
}
48
} catch (error) {
49
console.error("Error during image compression and copy:", error);
50
}
51
}

3. Operaciones con Git

A continuación, utilizamos la librería simple-git para cargar automáticamente las imágenes en el repositorio de GitHub:

1
import simpleGit from "simple-git";
2
3
const gitRepoDir = "/project/resources";
4
5
async function gitOperations() {
6
try {
7
const git = simpleGit(gitRepoDir);
8
await git.add("./*");
9
await git.commit("Update images");
10
await git.push("origin", "main");
11
console.log("Pushed changes to GitHub");
12
} catch (error) {
13
console.error("Error during Git operations:", error);
14
}
15
}

4. Actualizar las rutas de las imágenes

Finalmente, utilizamos la librería replace-in-file para reemplazar las rutas de las imágenes locales en el proyecto por las rutas en línea del CDN:

1
import { globby } from "globby";
2
import { replaceInFile } from "replace-in-file";
3
4
// Directorio y archivos donde se deben cambiar las rutas de las imágenes
5
const contentDir = "/project/myproject/src/content/**/*.{html,js,jsx,ts,tsx}";
6
const cdnBaseUrl =
7
"https://cdn.jsdelivr.net/gh/[NombreDeUsuarioGitHub]/resources/images";
8
9
async function updateImagePaths() {
10
try {
11
const files = await globby([contentDir]);
12
13
const replaceOptions = {
14
files,
15
from: /(["'])\/images\/(.+\.(jpg|jpeg|png|gif))/g,
16
to: `$1${cdnBaseUrl}/$2`,
17
};
18
19
const results = await replaceInFile(replaceOptions);
20
console.log(
21
"Modified files:",
22
results
23
.filter((result) => result.hasChanged)
24
.map((result) => result.file),
25
);
26
} catch (error) {
27
console.error("Error during updating image paths:", error);
28
}
29
}

5. Función principal

Integramos los pasos anteriores en una función principal:

1
(async function main() {
2
await compressAndCopyImages(imagesDir, targetDir);
3
await gitOperations();
4
await updateImagePaths();
5
})();

El código anterior realiza la compresión, el traslado, la carga y la actualización de las rutas de las imágenes, completando el proceso automatizado de gestión de imágenes locales a CDN. De esta manera, puedes utilizar imágenes locales durante el desarrollo y, en el entorno de producción, aprovechar la aceleración de imágenes mediante el CDN, mejorando la velocidad y el rendimiento del sitio web.