Skip to content

Commit 0e42728

Browse files
committed
feat: add image optimization plugin and convert images to webp format
1 parent 5a3bbe5 commit 0e42728

1 file changed

Lines changed: 79 additions & 3 deletions

File tree

vite.config.ts

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,101 @@
11
import { fileURLToPath, URL } from "node:url"
22
import fs from "fs/promises"
33

4-
import { UserConfig } from "vite"
4+
import { PluginOption, UserConfig } from "vite"
55
import { ViteSSGOptions } from "vite-ssg"
66
import generateSitemap from "vite-ssg-sitemap"
77
import vue from "@vitejs/plugin-vue"
88
import vueDevTools from "vite-plugin-vue-devtools"
9+
import { ViteImageOptimizer as viteImageOptimizer } from "vite-plugin-image-optimizer"
910

1011
import { projects } from "./src/script/projects"
1112
import type { CustomRouteMetadata } from "./src/types"
1213
import type { RouteRecordRaw } from "vue-router"
1314

1415
import * as child from "child_process"
16+
import { globSync } from "node:fs"
17+
import path from "node:path"
18+
import sharp from "sharp"
1519

16-
process.env.VITE_GIT_COMMIT_HASH = child.execSync("git rev-parse --short HEAD").toString()
20+
type ViteImageOptimizerOptions = Required<NonNullable<Parameters<typeof viteImageOptimizer>[0]>>
21+
22+
const imageOptimizerOptions: Pick<
23+
ViteImageOptimizerOptions,
24+
"jpg" | "jpeg" | "png" | "webp" | "avif"
25+
> = {
26+
jpg: { quality: 75 },
27+
png: { quality: 75 },
28+
webp: { quality: 75 },
29+
jpeg: { quality: 75 },
30+
avif: { quality: 75 },
31+
}
32+
33+
const convertToWebp: (webpOptions: sharp.WebpOptions) => PluginOption = (webpOptions) => {
34+
const generated: string[] = []
35+
36+
return {
37+
name: "convert-to-webp",
38+
apply: "build",
39+
enforce: "pre",
40+
41+
buildStart: async () => {
42+
const files = globSync("src/**/*.{jpg,jpeg,png}")
43+
for (const file of files) {
44+
const out = file.replace(/\.(jpg|jpeg|png)$/, ".webp")
45+
46+
try {
47+
await fs.access(out)
48+
// File exists, do nothing
49+
} catch {
50+
// File doesn't exist, generate it
51+
await sharp(file).webp(webpOptions).toFile(out)
52+
generated.push(out)
53+
console.log(`✓ ${path.basename(file)} → webp`)
54+
}
55+
}
56+
},
57+
58+
resolveId: async (source, importer) => {
59+
if (/\.(jpg|jpeg|png)$/.test(source) && importer) {
60+
const dir = path.dirname(importer)
61+
const resolved = path.resolve(dir, source)
62+
const webp = resolved.replace(/\.(jpg|jpeg|png)$/, ".webp")
63+
64+
try {
65+
await fs.access(webp)
66+
// File exists, redirect to webp version
67+
return webp
68+
} catch {
69+
// File doesn't exist, do nothing
70+
}
71+
}
72+
},
73+
74+
closeBundle: async () => {
75+
await Promise.all(
76+
generated.map((file) =>
77+
fs.rm(file).then(() => console.log(`🗑 ${path.basename(file)} deleted`)),
78+
),
79+
)
80+
},
81+
}
82+
}
1783

1884
const badUA = await fs.readFile("src/knownBadUA.txt", "utf-8")
1985

86+
process.env.VITE_GIT_COMMIT_HASH = child.execSync("git rev-parse --short HEAD").toString()
87+
2088
// https://vite.dev/config/
2189
export default {
22-
plugins: [vue(), vueDevTools()],
90+
build: {
91+
minify: "oxc",
92+
},
93+
plugins: [
94+
vue(),
95+
vueDevTools(),
96+
convertToWebp(imageOptimizerOptions.webp),
97+
viteImageOptimizer(imageOptimizerOptions),
98+
],
2399
resolve: {
24100
alias: {
25101
"@assets": fileURLToPath(new URL("./src/assets", import.meta.url)),

0 commit comments

Comments
 (0)