image optimization
This commit is contained in:
parent
47ac0b329c
commit
7b04c35c94
7 changed files with 85 additions and 18 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -4,17 +4,18 @@
|
|||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
"@types/bun": "^1.1.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/mime-types": "^2.1.4",
|
||||
"esbuild": "^0.23.0",
|
||||
"marked": "^13.0.3",
|
||||
"esbuild": "^0.23.1",
|
||||
"marked": "^14.1.0",
|
||||
"mime-types": "^2.1.35",
|
||||
"postcss": "^8.4.41",
|
||||
"preact": "^10.23.1"
|
||||
"preact": "^10.23.2",
|
||||
"sharp": "^0.33.5"
|
||||
}
|
||||
}
|
33
src/index.ts
33
src/index.ts
|
@ -4,11 +4,12 @@ export abstract class Plugin {
|
|||
renameTo?: string;
|
||||
abstract longLasting: boolean;
|
||||
abstract build?(): void;
|
||||
isBinary = false;
|
||||
|
||||
abstract rewriteFile(
|
||||
file: string,
|
||||
file: string | Buffer,
|
||||
filePath: string
|
||||
): Promise<string | undefined | null | void>;
|
||||
): Promise<Buffer | string | undefined | null | void>;
|
||||
}
|
||||
|
||||
import * as fs from "fs";
|
||||
|
@ -35,13 +36,14 @@ export default class SSSG {
|
|||
}
|
||||
|
||||
async build() {
|
||||
for(const plugin of this.plugins) {
|
||||
if(plugin.build) {
|
||||
console.time("Building..");
|
||||
for (const plugin of this.plugins) {
|
||||
if (plugin.build) {
|
||||
plugin.build();
|
||||
}
|
||||
}
|
||||
try {
|
||||
fs.rmSync(this.outputFolder, {recursive: true});
|
||||
fs.rmSync(this.outputFolder, { recursive: true });
|
||||
} catch {}
|
||||
|
||||
const sourceFiles = fs.readdirSync(this.inputFolder, {
|
||||
|
@ -66,7 +68,6 @@ export default class SSSG {
|
|||
z.rewriteTriggers.includes(type)
|
||||
);
|
||||
|
||||
|
||||
if (availablePlugins.length == 0) {
|
||||
const oldPath = path.join(file.parentPath, file.name);
|
||||
fs.cpSync(
|
||||
|
@ -82,12 +83,20 @@ export default class SSSG {
|
|||
file.parentPath,
|
||||
shortname +
|
||||
"." +
|
||||
(plugin.rewriteTriggers.includes("*") ? type : plugin.renameTo)
|
||||
(plugin.rewriteTriggers.includes("*") || plugin.renameTo == "keep"
|
||||
? type
|
||||
: plugin.renameTo)
|
||||
)
|
||||
.replace(this.inputFolder, this.outputFolder);
|
||||
let data = fs.readFileSync(oldPath).toString("utf8");
|
||||
let data: string | Buffer = fs.readFileSync(oldPath);
|
||||
|
||||
if (!plugin.isBinary) {
|
||||
data = data.toString("utf8");
|
||||
}
|
||||
|
||||
for await (const globalPlugin of globalPlugins) {
|
||||
if (!globalPlugin.isBinary && plugin.isBinary) continue;
|
||||
|
||||
const rewritten = await globalPlugin.rewriteFile(data, oldPath);
|
||||
if (!rewritten) continue;
|
||||
data = rewritten;
|
||||
|
@ -98,8 +107,14 @@ export default class SSSG {
|
|||
if (!rewrite) continue;
|
||||
|
||||
fs.mkdirSync(path.dirname(newPath), { recursive: true });
|
||||
fs.writeFileSync(newPath, rewrite);
|
||||
fs.writeFileSync(
|
||||
newPath,
|
||||
plugin.isBinary
|
||||
? new Uint8Array(rewrite as Buffer)
|
||||
: (rewrite as string)
|
||||
);
|
||||
}
|
||||
}
|
||||
console.timeEnd("Building..");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ export default class CompileTimeJS extends Plugin {
|
|||
rewriteTriggers = ["html", "*"]
|
||||
longLasting = false;
|
||||
build = undefined;
|
||||
|
||||
|
||||
async rewriteFile(file: string, filePath: string): Promise<string> {
|
||||
let input = file;
|
||||
const regex = /{&(.+)&}/gms;
|
||||
|
|
|
@ -3,7 +3,7 @@ import SSSG, { Plugin } from "..";
|
|||
import * as fs from "fs";
|
||||
import mime from "mime-types";
|
||||
|
||||
const script = `let reconnectTimeout;function connect(){console.log("[--dev] connecting to dev server");let ws=new WebSocket("ws://localhost:8080");ws.addEventListener("message",message=>{if(message.data=="refresh"){location.reload()}});ws.addEventListener("open",()=>{console.log("[--dev] connected")});ws.addEventListener("close",()=>{console.log("[--dev] socket closed, restarting in 1s");clearTimeout(reconnectTimeout);reconnectTimeout=setTimeout(()=>{connect()},1e3)})}window.addEventListener("load",()=>connect());`;
|
||||
const script = `let reconnectTimeout,waitingForReconnect=!1;function connect(){console.log("[dev] connecting to dev server");var e=new WebSocket("ws://localhost:8080");e.addEventListener("message",e=>{"refresh"==e.data&&location.reload()}),e.addEventListener("open",()=>{console.log("[dev] connected"),waitingForReconnect&&location.reload()}),e.addEventListener("close",()=>{console.log("[dev] socket closed, restarting in 1s"),clearTimeout(reconnectTimeout),reconnectTimeout=setTimeout(()=>{connect(),waitingForReconnect=!0},1e3)})}window.addEventListener("load",()=>connect());`;
|
||||
|
||||
export default class DevPlugin extends Plugin {
|
||||
build: undefined;
|
||||
|
@ -14,10 +14,9 @@ export default class DevPlugin extends Plugin {
|
|||
longLasting = true;
|
||||
server!: Server;
|
||||
allConnections: ServerWebSocket<number>[] = [];
|
||||
|
||||
|
||||
constructor(sssg: SSSG) {
|
||||
super();
|
||||
if (!process.argv.includes("--dev")) return;
|
||||
|
||||
fs.watch(
|
||||
sssg.inputFolder,
|
||||
|
|
53
src/plugins/image-optimization.ts
Normal file
53
src/plugins/image-optimization.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import { Plugin } from "..";
|
||||
import sharp from "sharp";
|
||||
|
||||
export default class ImageOptimization extends Plugin {
|
||||
build: undefined;
|
||||
|
||||
name = "image-optimization";
|
||||
rewriteTriggers = ["png", "gif", "jpg", "jpeg", "webp", "avif"];
|
||||
renameTo = "keep";
|
||||
isBinary = true;
|
||||
longLasting = false;
|
||||
|
||||
logging = true;
|
||||
|
||||
constructor(logging = true) {
|
||||
super();
|
||||
this.logging = logging;
|
||||
}
|
||||
|
||||
async rewriteFile(file: Buffer, filePath: string) {
|
||||
const nonOptimized = file;
|
||||
|
||||
const type = filePath.split(".").at(-1);
|
||||
let data: Buffer = file;
|
||||
if (type == "webp") {
|
||||
data = await sharp(file).webp({ lossless: true }).toBuffer();
|
||||
}
|
||||
if (type == "avif") {
|
||||
data = await sharp(file).avif({ lossless: true }).toBuffer();
|
||||
}
|
||||
if (type == "jpg" || type == "jpeg") {
|
||||
data = await sharp(file).jpeg({ quality: 100 }).toBuffer();
|
||||
}
|
||||
if (type == "png") {
|
||||
data = await sharp(file).png({ quality: 100 }).toBuffer();
|
||||
}
|
||||
if (type == "gif") {
|
||||
// not heavy optimizations, not a fan tbf, but whatever :shrug:
|
||||
data = await sharp(file, { animated: true })
|
||||
.gif({ colors: 16 })
|
||||
.toBuffer();
|
||||
}
|
||||
|
||||
if(nonOptimized.byteLength < data.byteLength) {
|
||||
if(this.logging) {
|
||||
console.log("❌ " + filePath + "("+nonOptimized.byteLength+"B) optimized was " + data.byteLength + "B. It has been skipped.");
|
||||
}
|
||||
data = nonOptimized;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import { Plugin } from "..";
|
||||
|
||||
export default class Variables extends Plugin {
|
||||
|
||||
name = "variables";
|
||||
rewriteTriggers = ["html", "*"];
|
||||
renameTo = undefined;
|
||||
|
|
Loading…
Reference in a new issue