如何利用jsdelivr免费CDN,通过脚本实现自动上传并替换本地图片路径

我们知道在生产环境中,将图片存储在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 对应起来

  1. 将资源上传到 GitHub 仓库
    首先,开发者需要将静态资源(如图片、JavaScript 文件、CSS 文件等)上传到 GitHub 仓库中的特定目录。例如,你可能有一个名为 my-project 的 GitHub 仓库,里面有一个 images 文件夹,存储了一些图片。

  2. 使用 jsdelivr CDN 进行访问
    一旦资源上传到 GitHub 仓库中,你可以通过 jsdelivr 提供的 URL 访问这些资源。jsdelivr 提供了一个与 GitHub 项目相关联的 CDN 地址,该地址遵循以下格式:

    1
    https://cdn.jsdelivr.net/gh/[GitHub用户名]/[仓库名]@[标签或分支]/[文件路径]
    • [GitHub用户名]:你的 GitHub 用户名。
    • [仓库名]:你上传资源的 GitHub 仓库名称。
    • [标签或分支]:你要使用的 GitHub 标签或分支(例如 mainv1.0)。
    • [文件路径]:资源在仓库中的路径。

    示例

    假设你的 GitHub 用户名是 johnsmith,你的仓库名是 my-project,你在 main 分支上有一个 images 文件夹,其中有一个名为 logo.png 的图片。你可以通过以下 jsdelivr CDN URL 来访问这个图片:

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

    在你的网页中,你可以使用这个 URL 来引用图片,这样 jsdelivr 就会从全球各地的服务器缓存中加速加载这个图片,提高加载速度。

  3. 自动同步更新
    当你更新 GitHub 仓库中的资源时,jsdelivr 会自动从 GitHub 上拉取最新的资源,保持 CDN 上的资源是最新的。这意味着只要你在 GitHub 仓库中上传了新版本的资源,jsdelivr 的 URL 就会自动更新,以提供最新的文件。

通过这种方式,开发者可以利用 jsdelivr CDN 的全球分发网络,加速从 GitHub 仓库中存储的静态资源的加载速度,提升用户体验。

实现步骤

1. 安装依赖

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

2. 压缩并搬迁图片

首先,使用sharp库对图片进行压缩,并保留文件夹结构将图片搬迁到目标目录。以下是实现代码:

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. Git操作

接下来,通过simple-git库自动将图片上传到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. 更新图片路径

最后,通过replace-in-file库将项目中引用的本地图片路径替换为线上路径:

1
import { globby } from "globby";
2
import { replaceInFile } from "replace-in-file";
3
4
// 需要更换图片路径的目录和文件
5
const contentDir = "/project/myproject/src/content/**/*.{html,js,jsx,ts,tsx}";
6
const cdnBaseUrl =
7
"https://cdn.jsdelivr.net/gh/[GitHub用户名]/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. 主函数

将上述步骤整合到一个主函数中:

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

以上代码实现了图片的压缩、搬迁、上传及路径替换,完成了从本地图片到CDN托管的自动化过程。这样,在本地开发时使用本地图片,生产环境中则使用CDN加速的图片,提高了网站的加载速度和性能。

美团外卖红包 饿了么红包 支付宝红包