如何利用jsdelivr免费CDN,通过脚本实现自动上传并替换本地图片路径
- 1271字
- 6分钟
- 2024-07-21
我们知道在生产环境中,将图片存储在CDN(内容分发网络)上,可以加快加载速度,提高用户体验。我最近遇到一个需求是这样的,在项目中会引用本地图片,假设是/images/xxx.{jpg,jpeg,png,gif}
等以方便本地开发,在开发完成后,会把images
目录下的所有图片压缩后搬迁到 /project/resources//images
中(resources是个git项目),并通过git自动上传到github,然后找出本地项目引用图片的路径,并更改为CDN路径。了解了整个流程,我们可以通过脚本来将这一过程自动化。首先我们先了解下jsdelivr实现CDN的方式是怎样的,如下:
jsdelivr CDN 和 GitHub 的关系
jsdelivr 是一个免费且可靠的内容分发网络(CDN)服务,允许开发者将静态资源存储在 GitHub 仓库中,并通过 jsdelivr 进行全球加速访问。具体来说,jsdelivr 能够通过提供一个 CDN 地址,将存储在 GitHub 仓库中的资源进行加速,从而使这些资源在全球范围内快速加载。
如何将 GitHub 项目与 jsdelivr 对应起来
-
将资源上传到 GitHub 仓库
首先,开发者需要将静态资源(如图片、JavaScript 文件、CSS 文件等)上传到 GitHub 仓库中的特定目录。例如,你可能有一个名为my-project
的 GitHub 仓库,里面有一个images
文件夹,存储了一些图片。 -
使用 jsdelivr CDN 进行访问
一旦资源上传到 GitHub 仓库中,你可以通过 jsdelivr 提供的 URL 访问这些资源。jsdelivr 提供了一个与 GitHub 项目相关联的 CDN 地址,该地址遵循以下格式:1https://cdn.jsdelivr.net/gh/[GitHub用户名]/[仓库名]@[标签或分支]/[文件路径][GitHub用户名]
:你的 GitHub 用户名。[仓库名]
:你上传资源的 GitHub 仓库名称。[标签或分支]
:你要使用的 GitHub 标签或分支(例如main
或v1.0
)。[文件路径]
:资源在仓库中的路径。
示例:
假设你的 GitHub 用户名是
johnsmith
,你的仓库名是my-project
,你在main
分支上有一个images
文件夹,其中有一个名为logo.png
的图片。你可以通过以下 jsdelivr CDN URL 来访问这个图片:1https://cdn.jsdelivr.net/gh/johnsmith/my-project@main/images/logo.png在你的网页中,你可以使用这个 URL 来引用图片,这样 jsdelivr 就会从全球各地的服务器缓存中加速加载这个图片,提高加载速度。
-
自动同步更新
当你更新 GitHub 仓库中的资源时,jsdelivr 会自动从 GitHub 上拉取最新的资源,保持 CDN 上的资源是最新的。这意味着只要你在 GitHub 仓库中上传了新版本的资源,jsdelivr 的 URL 就会自动更新,以提供最新的文件。
通过这种方式,开发者可以利用 jsdelivr CDN 的全球分发网络,加速从 GitHub 仓库中存储的静态资源的加载速度,提升用户体验。
实现步骤
1. 安装依赖
1pnpm add sharp fs-extra globby simple-git replace-in-file;
2. 压缩并搬迁图片
首先,使用sharp
库对图片进行压缩,并保留文件夹结构将图片搬迁到目标目录。以下是实现代码:
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操作
接下来,通过simple-git
库自动将图片上传到GitHub仓库:
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. 更新图片路径
最后,通过replace-in-file
库将项目中引用的本地图片路径替换为线上路径:
1import { globby } from "globby";2import { replaceInFile } from "replace-in-file";3
4// 需要更换图片路径的目录和文件5const contentDir = "/project/myproject/src/content/**/*.{html,js,jsx,ts,tsx}";6const cdnBaseUrl =7 "https://cdn.jsdelivr.net/gh/[GitHub用户名]/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. 主函数
将上述步骤整合到一个主函数中:
1(async function main() {2 await compressAndCopyImages(imagesDir, targetDir);3 await gitOperations();4 await updateImagePaths();5})();
以上代码实现了图片的压缩、搬迁、上传及路径替换,完成了从本地图片到CDN托管的自动化过程。这样,在本地开发时使用本地图片,生产环境中则使用CDN加速的图片,提高了网站的加载速度和性能。


