如何利用 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 加速的圖片,提高了網站的加載速度和性能。