feat: switch to mantine-hooks, random-js, add cssnano & aggressive bundle optimizations, remove chance/usehooks/lodash

This commit is contained in:
2025-08-09 13:40:04 -05:00
parent 75913606f4
commit d668a21750
5 changed files with 820 additions and 56 deletions

View File

@@ -10,20 +10,21 @@
},
"dependencies": {
"@heroicons/react": "^2.2.0",
"@mantine/hooks": "^8.2.4",
"@tailwindcss/vite": "^4.1.11",
"@use-it/event-listener": "^0.1.7",
"chance": "^1.1.13",
"cssnano": "^7.1.0",
"random-js": "^2.1.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"tailwindcss": "^4.1.11",
"usehooks-ts": "^3.1.1"
"tailwindcss": "^4.1.11"
},
"devDependencies": {
"@types/chance": "^1.1.7",
"@types/node": "^24.2.1",
"@types/react": "^19.1.9",
"@types/react-dom": "^19.1.7",
"@vitejs/plugin-react": "^5.0.0",
"rollup-plugin-visualizer": "^6.0.3",
"typescript": "^5.9.2",
"vite": "^7.1.1",
"vite-tsconfig-paths": "^5.1.4"

806
pnpm-lock.yaml generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
import { useInterval, useWindowSize, useToggle } from "usehooks-ts";
import { useViewportSize, useToggle } from "@mantine/hooks";
import useBackground from "@/utils/useBackground";
import Post from "@/components/Post";
@@ -7,24 +7,18 @@ import {
EyeIcon,
EyeSlashIcon,
} from "@heroicons/react/24/solid";
import { useMemo } from "react";
import { useMemo, useState } from "react";
function App() {
const { width, height } = useWindowSize();
const { width, height } = useViewportSize();
const { svg, backgrounds, regenerate } = useBackground({
width,
height,
ratio: 0.4,
});
const [postHidden, toggleHidden] = useToggle(false);
const [postHidden, toggleHidden] = useToggle([false, true]);
const [iconSpinning, , setIconSpinning] = useToggle(false);
useInterval(
() => {
setIconSpinning(false);
},
iconSpinning ? 200 : null
);
const [iconSpinning, toggleIconSpinning] = useToggle([false, true]);
const style = useMemo(() => {
return {
@@ -43,8 +37,9 @@ function App() {
<button
className="block p-2 w-10 h-10 rounded mx-auto xs:mx-0 xs:ml-5 mt-5 shadow-inner-md bg-zinc-700 text-zinc-100 button"
onClick={() => {
setIconSpinning(true);
toggleIconSpinning(true);
regenerate();
setTimeout(() => toggleIconSpinning(false), 200);
}}
>
<ArrowPathIcon
@@ -55,7 +50,7 @@ function App() {
</button>
<button
className="block p-2 w-10 h-10 rounded mx-auto xs:mx-0 xs:ml-5 mt-5 shadow-inner-md bg-zinc-700 text-zinc-100 button"
onClick={toggleHidden}
onClick={() => toggleHidden()}
>
{postHidden ? <EyeIcon /> : <EyeSlashIcon />}
</button>

View File

@@ -1,4 +1,4 @@
import { Chance } from "chance";
import { Random } from "random-js";
import { useMemo, useState } from "react";
import ReactDOMServer from "react-dom/server";
import { getEdgePoint } from "@/utils/helpers";
@@ -15,20 +15,20 @@ interface useBackgroundReturn {
svg: string;
}
const chance = Chance();
const random = new Random();
const palettes = [
// ["#5e1e1e", "#141414", "#400000", "#7a0000", "#2b0059", "#000c59", "#850082", "#850052"],
["#ed625d", "#42b6c6", "#f79f88", "#446ba6", "#4b95f0", "#d16ba5"],
];
const generateBackground = (): string[] => {
const palette = chance.pick(palettes);
const palette = random.pick(palettes);
return Array(5)
.fill(null)
.map(() => chance.pickone(palette))
.map(() => random.pick(palette))
.map((color) => {
const [x, y] = getEdgePoint(
chance.integer({ min: 0, max: 400 }),
random.integer(0, 400),
100,
100
);
@@ -60,7 +60,7 @@ const useBackground = ({
type="fractalNoise"
baseFrequency="2.1"
numOctaves="2"
seed={chance.natural()}
seed={random.integer(0, 1000000)}
stitchTiles="stitch"
/>
</filter>

View File

@@ -2,6 +2,8 @@ import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";
import tailwindcss from "@tailwindcss/vite";
import { visualizer } from "rollup-plugin-visualizer";
import cssnano from "cssnano";
// https://vitejs.dev/config/
export default ({ mode }) => {
@@ -9,9 +11,31 @@ export default ({ mode }) => {
return defineConfig({
base: "/",
plugins: [react(), tsconfigPaths(), tailwindcss()],
plugins: [
react(),
tsconfigPaths(),
tailwindcss(),
cssnano(),
visualizer({
template: "treemap",
open: true, // Automatically open the report in your browser after build
filename: "stats.html", // Output file name
gzipSize: true, // Show gzip size
brotliSize: true, // Show brotli size
}),
],
build: {
chunkSizeWarningLimit: 650,
rollupOptions: {
treeshake: {
// Remove unused module exports
moduleSideEffects: false,
// Optimize property access
propertyReadSideEffects: false,
// Remove unused imports
tryCatchDeoptimization: false,
},
},
},
});
};