perf: optimize blog assets for low bandwidth

This commit is contained in:
liumangmang
2026-05-11 15:51:32 +08:00
parent 119bfd49c5
commit 77024b5809
7 changed files with 36 additions and 13 deletions
+4
View File
@@ -8,12 +8,16 @@ server {
gzip on; gzip on;
gzip_vary on; gzip_vary on;
gzip_min_length 1024; gzip_min_length 1024;
gzip_comp_level 6;
gzip_proxied any;
gzip_types gzip_types
application/javascript application/javascript
application/json application/json
application/rss+xml
application/xml application/xml
image/svg+xml image/svg+xml
text/css text/css
text/javascript
text/plain text/plain
text/xml; text/xml;
+20 -10
View File
@@ -26,7 +26,7 @@ function formatBytes(bytes) {
async function optimizeImage(inputPath, outputPath, options = {}) { async function optimizeImage(inputPath, outputPath, options = {}) {
const { width, quality = 80, outputExt = '.webp' } = options; const { width, quality = 80, outputExt = '.webp' } = options;
const originalSize = await getFileSize(inputPath); const originalSize = await getFileSize(inputPath);
let pipeline = sharp(inputPath); let pipeline = sharp(inputPath);
if (width) { if (width) {
@@ -40,19 +40,20 @@ async function optimizeImage(inputPath, outputPath, options = {}) {
} }
const buffer = await pipeline.toBuffer(); const buffer = await pipeline.toBuffer();
const optimizedSize = buffer.length;
// For standard images, if webp is larger, we'll keep it if it's the specific target like bgImage
// but for general article images we might skip. // Threshold: webp must be at least 10% smaller than original
const isTargeted = inputPath.includes(SOURCE_DIR); const isTargeted = inputPath.includes(SOURCE_DIR);
if (!isTargeted && buffer.length >= originalSize && outputExt === '.webp') { const reductionRatio = (originalSize - optimizedSize) / originalSize;
console.log(`Skipping ${path.basename(inputPath)}: Optimized size (${formatBytes(buffer.length)}) >= original (${formatBytes(originalSize)})`);
if (!isTargeted && reductionRatio < 0.1 && outputExt === '.webp') {
console.log(`Skipping ${path.basename(inputPath)}: Reduction ${ (reductionRatio * 100).toFixed(2) }% < 10% threshold`);
return null; return null;
} }
await fs.mkdir(path.dirname(outputPath), { recursive: true }); await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(outputPath, buffer); await fs.writeFile(outputPath, buffer);
const optimizedSize = buffer.length;
return { return {
inputPath, inputPath,
outputPath, outputPath,
@@ -60,7 +61,7 @@ async function optimizeImage(inputPath, outputPath, options = {}) {
outputName: path.basename(outputPath), outputName: path.basename(outputPath),
originalSize, originalSize,
optimizedSize, optimizedSize,
reduction: ((originalSize - optimizedSize) / originalSize * 100).toFixed(2) + '%' reduction: (reductionRatio * 100).toFixed(2) + '%'
}; };
} }
@@ -89,7 +90,16 @@ async function main() {
if (res) results.push(res); if (res) results.push(res);
} }
// 4. Optimize Article Images (In-place WebP generation) // 4. Optimize Cover Images in Public Assets
const coverImages = await glob('src/.vuepress/public/assets/images/cover*.{jpg,jpeg,png}');
console.log(`Found ${coverImages.length} cover images to process...`);
for (const img of coverImages) {
const outputWebp = img.replace(path.extname(img), '.webp');
const res = await optimizeImage(img, outputWebp, { quality: 80 });
if (res) results.push(res);
}
// 5. Optimize Article Images (In-place WebP generation)
const articleImages = await glob('src/**/*.{jpg,jpeg,png}', { const articleImages = await glob('src/**/*.{jpg,jpeg,png}', {
ignore: ['src/.vuepress/dist/**', 'src/.vuepress/public/**'] ignore: ['src/.vuepress/dist/**', 'src/.vuepress/public/**']
}); });
+3
View File
@@ -14,6 +14,9 @@ export default defineUserConfig({
head: [['link', { rel: 'icon', href: '/favicon.png' }]], head: [['link', { rel: 'icon', href: '/favicon.png' }]],
shouldPrefetch: false,
shouldPreload: false,
theme, theme,
bundler: viteBundler({ bundler: viteBundler({
viteOptions: { viteOptions: {
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+8 -1
View File
@@ -116,7 +116,14 @@ export default hopeTheme(
blog: true, blog: true,
// 启用本地搜索 // 启用本地搜索
search: true, search: {
isSearchable: (page) =>
!page.path.includes('/work/log/') &&
!page.path.includes('/demo/') &&
!page.path.includes('/accounts/') &&
!page.path.includes('SpringSecurity'),
maxSuggestions: 10,
},
// 组件配置 // 组件配置
components: { components: {
-1
View File
@@ -1,7 +1,6 @@
--- ---
title: 账号密码管理 title: 账号密码管理
index: false index: false
search: false
navbar: false navbar: false
sidebar: false sidebar: false
breadcrumb: false breadcrumb: false
+1 -1
View File
@@ -1,6 +1,6 @@
--- ---
icon: circle-info icon: circle-info
cover: /assets/images/cover3.jpg cover: /assets/images/cover3.webp
date: 2025-05-06 date: 2025-05-06
--- ---