vite.config.js
Rama main · réplica de lectura del repositorio original.
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
import { readFileSync } from "node:fs";
import { execSync } from "node:child_process";
import { ViteImageOptimizer } from "vite-plugin-image-optimizer";
import { VitePWA } from "vite-plugin-pwa";
import { sri } from "vite-plugin-sri3";
import { compression } from "vite-plugin-compression2";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const packageJson = JSON.parse(
readFileSync(new URL("./package.json", import.meta.url), "utf-8"),
);
function resolveAppVersion() {
const packageVersion = packageJson.version;
if (packageVersion && packageVersion !== "0.0.0") {
return packageVersion;
}
try {
return execSync("git describe --tags --always --dirty", {
encoding: "utf-8",
}).trim();
} catch {
return packageVersion || "unknown";
}
}
const appVersion = resolveAppVersion();
export default defineConfig(({ command, mode }) => {
const isProductionBuild = command === "build" && mode === "production";
return {
plugins: [
react(),
VitePWA({
registerType: "autoUpdate",
injectRegister: "auto",
includeAssets: [
"favicon.svg",
"apple-touch-icon.png",
"maskable-icon.svg",
"safari-pinned-tab.svg",
],
manifest: {
name: "Tuning Visualizer",
short_name: "TuningViz",
start_url: "/",
scope: "/",
display: "standalone",
background_color: "#101214",
theme_color: "#ff6a00",
icons: [
{
src: "/maskable-icon-192.png",
sizes: "192x192",
type: "image/png",
purpose: "any maskable",
},
{
src: "/maskable-icon-512.png",
sizes: "512x512",
type: "image/png",
purpose: "any maskable",
},
],
},
workbox: {
globPatterns: ["**/*.{js,css,html,svg,png,webmanifest}"],
cleanupOutdatedCaches: true,
navigateFallback: "/index.html",
},
devOptions: {
enabled: false,
},
}),
...(isProductionBuild
? [
ViteImageOptimizer({
png: { quality: 80 },
jpeg: { quality: 80 },
jpg: { quality: 80 },
webp: { quality: 80 },
avif: { quality: 50 },
}),
sri(),
compression({
algorithms: ["gzip", "brotliCompress"],
exclude: [/\.(png|jpe?g|webp|avif|gif|woff2?)$/i],
deleteOriginalAssets: false,
}),
]
: []),
],
define: {
"import.meta.env.VITE_APP_VERSION": JSON.stringify(appVersion),
},
css: {
transformer: "lightningcss",
lightningcss: {
targets: { chrome: 109, safari: 15, firefox: 102, edge: 109 },
drafts: { nesting: true, customMedia: true },
},
},
build: {
target: ["chrome109", "safari15", "firefox102", "edge109"],
minify: isProductionBuild ? "oxc" : false,
cssMinify: "lightningcss",
rolldownOptions: {
output: {
...(isProductionBuild
? { minify: { compress: { dropConsole: true }, mangle: true } }
: {}),
manualChunks(id) {
if (id.includes("/@dmnerd/microtonal/")) {
return "theory";
}
if (!id.includes("node_modules")) {
return;
}
if (id.includes("/react/") || id.includes("/react-dom/")) {
return "react-core";
}
if (
id.includes("/react-icons/") ||
id.includes("/react-hot-toast/") ||
id.includes("/clsx/")
) {
return "ui-kit";
}
if (id.includes("/fuse.js/")) {
return "search";
}
if (id.includes("/json-edit-react/")) {
return "editor";
}
if (id.includes("/react-qr-code/") || id.includes("/qr.js/")) {
return "share";
}
if (id.includes("/zustand/")) {
return "state";
}
return "vendor";
},
},
},
},
resolve: {
alias: [
{ find: "@app", replacement: resolve(__dirname, "src/app") },
{ find: "@features", replacement: resolve(__dirname, "src/features") },
{ find: "@shared", replacement: resolve(__dirname, "src/shared") },
{ find: "@domain", replacement: resolve(__dirname, "src/domain") },
{ find: "@styles", replacement: resolve(__dirname, "src/styles") },
{ find: "@", replacement: resolve(__dirname, "src") },
],
},
};
});