How to Use jsdelivr Free CDN to Automatically Upload and Replace Local Image Paths via Script
- 827Words
- 4Minutes
- 21 Jul, 2024
In production environments, storing images on a CDN (Content Delivery Network) can speed up loading times and improve user experience. Recently, I encountered a requirement to reference local images in a project, such as /images/xxx.{jpg,jpeg,png,gif}
, for ease of local development. After development is completed, all images in the images
directory need to be compressed and moved to /project/resources/images
(resources is a git project), automatically uploaded to GitHub via git, and local project image paths need to be found and changed to CDN paths. Understanding the whole process, we can automate it with a script. First, let’s understand how jsdelivr implements CDN:
Relationship between jsdelivr CDN and GitHub
jsdelivr is a free and reliable CDN service that allows developers to store static resources in a GitHub repository and accelerate access globally via jsdelivr. Specifically, jsdelivr can provide a CDN address that accelerates resources stored in a GitHub repository, making these resources load quickly worldwide.
How to Associate a GitHub Project with jsdelivr
-
Upload Resources to GitHub Repository
First, developers need to upload static resources (such as images, JavaScript files, CSS files, etc.) to a specific directory in the GitHub repository. For example, you might have a GitHub repository namedmy-project
with animages
folder storing some images. -
Access via jsdelivr CDN
Once resources are uploaded to the GitHub repository, you can access them via a URL provided by jsdelivr. jsdelivr provides a CDN address associated with the GitHub project, which follows this format:1https://cdn.jsdelivr.net/gh/[GitHubUsername]/[RepositoryName]@[TagOrBranch]/[FilePath][GitHubUsername]
: Your GitHub username.[RepositoryName]
: The name of your GitHub repository.[TagOrBranch]
: The GitHub tag or branch you want to use (e.g.,main
orv1.0
).[FilePath]
: The path to the resource in the repository.
Example:
Suppose your GitHub username is
johnsmith
, your repository name ismy-project
, and you have animages
folder in themain
branch with a file namedlogo.png
. You can access this image via the following jsdelivr CDN URL:1https://cdn.jsdelivr.net/gh/johnsmith/my-project@main/images/logo.pngOn your web page, you can use this URL to reference the image, allowing jsdelivr to speed up loading from global server caches, improving load times.
-
Automatic Synchronization
When you update resources in the GitHub repository, jsdelivr will automatically pull the latest resources from GitHub, ensuring the CDN resources are up to date. This means that as long as you upload new versions of resources to the GitHub repository, jsdelivr’s URL will automatically update to provide the latest files.
Using this method, developers can leverage jsdelivr CDN’s global distribution network to accelerate the loading speed of static resources stored in GitHub repositories, enhancing user experience.
Implementation Steps
1. Install Dependencies
1pnpm add sharp fs-extra globby simple-git replace-in-file;
2. Compress and Move Images
First, use the sharp
library to compress images, retaining the folder structure, and move the images to the target directory. Here is the implementation code:
1import { promises as fs } from "fs";2import path from "path";3import sharp from "sharp";4import fse from "fs-extra";5import { globby } from "globby";6
7const imagesDir = "/project/myproject/public/images";8const targetDir = "/project/resources/images";9
10async 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. Git Operations
Next, automatically upload the images to the GitHub repository via the simple-git
library:
1import simpleGit from "simple-git";2
3const gitRepoDir = "/project/resources";4
5async 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. Update Image Paths
Finally, use the replace-in-file
library to replace the local image paths referenced in the project with the online paths:
1import { globby } from "globby";2import { replaceInFile } from "replace-in-file";3
4// Directory and files where image paths need to be changed5const contentDir = "/project/myproject/src/content/**/*.{html,js,jsx,ts,tsx}";6const cdnBaseUrl =7 "https://cdn.jsdelivr.net/gh/[GitHubUsername]/resources/images";8
9async 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 results23 .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. Main Function
Integrate the above steps into a main function:
1(async function main() {2 await compressAndCopyImages(imagesDir, targetDir);3 await gitOperations();4 await updateImagePaths();5})();
The above code compresses, moves, uploads, and replaces the paths of images, completing the automated process from local images to CDN hosting. This way, you can use local images during local development and CDN-accelerated images in production, improving website loading speed and performance.