optimization

This commit is contained in:
lovebird 2025-03-09 14:18:01 +01:00
parent 6888866f0b
commit df27705b43
10 changed files with 10855 additions and 220 deletions

View File

@ -3,6 +3,8 @@ import tailwindcss from '@tailwindcss/vite'
import { imagetools } from "imagetools"
import react from "@astrojs/react"
import mdx from "@astrojs/mdx";
import { defineConfig } from 'astro/config';
import compress from 'vite-plugin-compression';
export default defineConfig({
devToolbar: {
@ -14,13 +16,22 @@ export default defineConfig({
},
vite: {
plugins: [
tailwindcss()
tailwindcss({
config: './tailwind.config.cjs',
jit: true
}),
compress({
algorithm: 'gzip', // You can also use 'brotliCompress' for Brotli
threshold: 1024, // Compress files larger than 1KB
deleteOriginFile: false, // Keep original files (optional)
})
],
build: {
target: 'esnext',
assetsDir: './assets',
modulePreload: { polyfill: false },
commonjsOptions: { esmExternals: true }
commonjsOptions: { esmExternals: true },
assetsInlineLimit: 1024
},
ssr: {
external: ['cacache', 'glob', 'xlsx', 'sharp', '@polymech/kbot-d']

View File

@ -1,107 +1,107 @@
// @ts-check
import crypto from "node:crypto";
import objectHash from "object-hash";
import getImageSources from "./getImageSources.js";
import getProcessedImage from "./getProcessedImage.js";
import getArtDirectedImages from "./getArtDirectedImages.js";
import pMap from "p-map";
const imagesData = new Map();
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default async function ({
src,
type,
sizes: imagesizes,
format,
breakpoints,
placeholder,
fallbackFormat,
includeSourceFormat,
formatOptions,
artDirectives,
transformConfigs,
}) {
try {
const args = Array.from(arguments);
const hash = objectHash(args);
if (imagesData.has(hash)) {
return imagesData.get(hash);
}
const start = performance.now();
const { path, base, rest, image, imageWidth, imageHeight, imageFormat } =
await getProcessedImage(src, transformConfigs);
await delay(250);
src = path;
rest.aspect = `${imageWidth / imageHeight}`;
if (!fallbackFormat) {
fallbackFormat = imageFormat;
}
// Fetch both image sources and art-directed images
const [mainImage, artDirectedImages] = await pMap(
[
async () =>
await getImageSources(
src,
base,
image,
format,
imageWidth,
imagesizes,
breakpoints,
placeholder,
imageFormat,
formatOptions,
fallbackFormat,
includeSourceFormat,
rest
),
async () => {
await delay(250);
return await getArtDirectedImages(
artDirectives,
placeholder,
format,
imagesizes,
breakpoints,
fallbackFormat,
includeSourceFormat,
formatOptions,
rest
);
},
],
async (task) => await task(),
{ concurrency: 1 }
);
// Ensure artDirectedImages is an array
const images = Array.isArray(artDirectedImages) ? [...artDirectedImages, mainImage] : [mainImage];
const uuid = crypto.randomBytes(4).toString("hex").toUpperCase();
const returnObject = {
uuid,
images,
};
imagesData.set(hash, returnObject);
const end = performance.now();
console.log(
`Responsive Image sets generated for ${type} at ${args[0].src} in ${end - start}ms`
);
return returnObject;
} catch (error) {
console.error("Error processing images:", error);
throw error;
}
}
// @ts-check
import crypto from "node:crypto";
import objectHash from "object-hash";
import getImageSources from "./getImageSources.js";
import getProcessedImage from "./getProcessedImage.js";
import getArtDirectedImages from "./getArtDirectedImages.js";
import pMap from "p-map";
const imagesData = new Map();
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default async function ({
src,
type,
sizes: imagesizes,
format,
breakpoints,
placeholder,
fallbackFormat,
includeSourceFormat,
formatOptions,
artDirectives,
transformConfigs,
}) {
try {
const args = Array.from(arguments);
const hash = objectHash(args);
if (imagesData.has(hash)) {
return imagesData.get(hash);
}
const start = performance.now();
const { path, base, rest, image, imageWidth, imageHeight, imageFormat } =
await getProcessedImage(src, transformConfigs);
await delay(100);
src = path;
rest.aspect = `${imageWidth / imageHeight}`;
if (!fallbackFormat) {
fallbackFormat = imageFormat;
}
// Fetch both image sources and art-directed images
const [mainImage, artDirectedImages] = await pMap(
[
async () =>
await getImageSources(
src,
base,
image,
format,
imageWidth,
imagesizes,
breakpoints,
placeholder,
imageFormat,
formatOptions,
fallbackFormat,
includeSourceFormat,
rest
),
async () => {
await delay(100);
return await getArtDirectedImages(
artDirectives,
placeholder,
format,
imagesizes,
breakpoints,
fallbackFormat,
includeSourceFormat,
formatOptions,
rest
);
},
],
async (task) => await task(),
{ concurrency: 1 }
);
// Ensure artDirectedImages is an array
const images = Array.isArray(artDirectedImages) ? [...artDirectedImages, mainImage] : [mainImage];
const uuid = crypto.randomBytes(4).toString("hex").toUpperCase();
const returnObject = {
uuid,
images,
};
imagesData.set(hash, returnObject);
const end = performance.now();
console.log(
`Responsive Image sets generated for ${type} at ${args[0].src} in ${end - start}ms`
);
return returnObject;
} catch (error) {
console.error("Error processing images:", error);
throw error;
}
}

View File

@ -1,91 +1,91 @@
// @ts-check
import getSrcset from "./getSrcset.js";
import getConfigOptions from "./getConfigOptions.js";
import getFallbackImage from "./getFallbackImage.js";
import pMap from "p-map";
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export default async function getImageSources(
src,
base,
image,
format,
imageWidth,
imagesizes,
breakpoints,
placeholder,
imageFormat,
formatOptions,
fallbackFormat,
includeSourceFormat,
rest
) {
try {
const calculatedConfigs = getConfigOptions(
imageWidth,
imagesizes,
breakpoints,
format,
imageFormat,
fallbackFormat,
includeSourceFormat
);
const { formats, requiredBreakpoints } = calculatedConfigs;
imagesizes = calculatedConfigs.imagesizes;
const maxWidth = requiredBreakpoints[requiredBreakpoints.length - 1];
const sliceLength = -(maxWidth.toString().length + 2);
const sources = await pMap(
formats,
async (format) => {
try {
await delay(250);
const srcset = await getSrcset(src, base, requiredBreakpoints, format, {
...rest,
...formatOptions[format],
});
const srcsets = srcset.split(", ");
const srcObject =
format === fallbackFormat
? { src: srcsets[srcsets.length - 1].slice(0, sliceLength) }
: {};
return {
...srcObject,
format,
srcset,
};
} catch (error) {
console.error(`Error processing format ${format}:`, error);
return null;
}
},
{ concurrency: 1 }
);
const filteredSources = sources.filter(Boolean);
const sizes = {
width: maxWidth,
height: Math.round(maxWidth / rest.aspect),
};
const fallback = await getFallbackImage(
src,
placeholder,
image,
fallbackFormat,
formatOptions,
rest
)
return { sources: filteredSources, sizes, fallback, imagesizes };
} catch (error) {
console.error("Error in getImageSources:", error);
return { sources: [], sizes: {}, fallback: null, imagesizes: null };
}
}
// @ts-check
import getSrcset from "./getSrcset.js";
import getConfigOptions from "./getConfigOptions.js";
import getFallbackImage from "./getFallbackImage.js";
import pMap from "p-map";
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export default async function getImageSources(
src,
base,
image,
format,
imageWidth,
imagesizes,
breakpoints,
placeholder,
imageFormat,
formatOptions,
fallbackFormat,
includeSourceFormat,
rest
) {
try {
const calculatedConfigs = getConfigOptions(
imageWidth,
imagesizes,
breakpoints,
format,
imageFormat,
fallbackFormat,
includeSourceFormat
);
const { formats, requiredBreakpoints } = calculatedConfigs;
imagesizes = calculatedConfigs.imagesizes;
const maxWidth = requiredBreakpoints[requiredBreakpoints.length - 1];
const sliceLength = -(maxWidth.toString().length + 2);
const sources = await pMap(
formats,
async (format) => {
try {
await delay(100);
const srcset = await getSrcset(src, base, requiredBreakpoints, format, {
...rest,
...formatOptions[format],
});
const srcsets = srcset.split(", ");
const srcObject =
format === fallbackFormat
? { src: srcsets[srcsets.length - 1].slice(0, sliceLength) }
: {};
return {
...srcObject,
format,
srcset,
};
} catch (error) {
console.error(`Error processing format ${format}:`, error);
return null;
}
},
{ concurrency: 1 }
);
const filteredSources = sources.filter(Boolean);
const sizes = {
width: maxWidth,
height: Math.round(maxWidth / rest.aspect),
};
const fallback = await getFallbackImage(
src,
placeholder,
image,
fallbackFormat,
formatOptions,
rest
)
return { sources: filteredSources, sizes, fallback, imagesizes };
} catch (error) {
console.error("Error in getImageSources:", error);
return { sources: [], sizes: {}, fallback: null, imagesizes: null };
}
}

View File

@ -1,12 +1,12 @@
export default {
"environment": "dev",
"environment": "build",
"isSsrBuild": false,
"projectBase": "",
"publicDir": "C:\\Users\\zx\\Desktop\\polymech\\polymech-site\\public\\",
"rootDir": "C:\\Users\\zx\\Desktop\\polymech\\polymech-site\\",
"mode": "dev",
"outDir": "dist",
"assetsDir": "/_astro",
"mode": "production",
"outDir": "C:\\Users\\zx\\Desktop\\polymech\\polymech-site\\dist\\",
"assetsDir": "_astro",
"sourcemap": false,
"assetFileNames": "/_astro/[name]@[width].[hash][extname]"
}

235
public/css/global.css Normal file
View File

@ -0,0 +1,235 @@
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@layer components {
.prose-styles {
@apply hover:prose-a:text-black prose prose-blockquote:border-l-black prose-blockquote:text-neutral-600 prose-code:text-black prose-headings:text-black text-neutral-600 prose-pre:rounded-xl prose-pre:p-4 max-w-none prose-headings:font-medium prose-pre:normal-case prose-pre:bg-white;
/* Base layout classes */
@apply prose max-w-3xl pt-0 mx-auto;
}
.simple-prose-styles {
@apply prose text-xs prose-headings:text-xs prose-pre:normal-case;
}
}
@layer base {
a {
@apply text-blue-400 no-underline transition-colors;
}
a:hover {
@apply underline;
}
}
@layer base {
table {
@apply min-w-full border-collapse;
}
table thead {
@apply bg-gray-200;
}
table th {
@apply py-3 px-6 text-left text-xs font-medium text-gray-600 uppercase tracking-wider;
}
table td {
@apply py-4 px-6 border-b border-gray-200;
}
table tbody tr {
@apply transition-colors;
}
table tbody tr:nth-child(odd) {
@apply bg-white;
}
table tbody tr:nth-child(even) {
@apply bg-gray-50;
}
table tbody tr:nth-child(odd):hover {
@apply bg-orange-50;
}
table tbody tr:nth-child(even):hover {
@apply bg-orange-100;
}
}
@layer base {
.astro-imagetools-img {
@apply min-w-full border-collapse rounded-lg overflow-hidden;
background-image: none !important;
object-fit: contain;
}
.lightbox-main{
background-image: none !important;
}
}
@layer base {
.specs-table {
@apply min-w-full border-collapse rounded-lg overflow-hidden;
}
.specs-table thead {
@apply bg-gray-200;
}
.specs-table th {
@apply py-3 px-6 text-left text-xs text-gray-600 uppercase tracking-wider;
}
.specs-table td {
@apply py-4 px-6 border-b border-gray-200;
}
.specs-table tbody tr {
@apply transition-colors;
}
.specs-table tbody tr:nth-child(odd) {
@apply bg-white;
}
.specs-table tbody tr:nth-child(even) {
@apply bg-gray-50;
}
.specs-table tbody tr:nth-child(odd):hover {
@apply bg-orange-50;
}
.specs-table tbody tr:nth-child(even):hover {
@apply bg-orange-100;
}
/* Bold the first column cells */
.specs-table th:first-child,
.specs-table td:first-child {
@apply font-semibold;
}
}
@layer components {
.table-default {
@apply min-w-full border-collapse shadow-lg;
}
.table-default thead {
@apply bg-gray-200;
}
.table-default th {
@apply py-3 px-6 text-left text-xs font-medium text-gray-600 uppercase tracking-wider;
}
.table-default td {
@apply py-4 px-6 border-b border-gray-200;
}
.table-default tbody tr {
@apply transition-colors;
}
/* Alternating row colors */
.table-default tbody tr:nth-child(odd) {
@apply bg-white;
}
.table-default tbody tr:nth-child(even) {
@apply bg-gray-50;
}
/* Hover effects with orange tint */
.table-default tbody tr:nth-child(odd):hover {
@apply bg-orange-50;
}
.table-default tbody tr:nth-child(even):hover {
@apply bg-orange-100;
}
}
@theme {
/* Typography*/
--font-sans: "Inter", sans-serif;
--font-mono: "IBM PLex Mono", monospace;
--text-xs:1rem;
/* Colors */
--color-orange-50: hsl(22, 100%, 96%);
--color-orange-100: hsl(25, 100%, 91%);
--color-orange-200: hsl(22, 100%, 82%);
--color-orange-300: hsl(20, 100%, 71%);
--color-orange-400: hsl(16, 100%, 60%);
--color-orange-500: hsl(14, 100%, 52%);
--color-orange-600: hsl(9, 100%, 50%);
--color-orange-700: hsl(6, 98%, 40%);
--color-orange-800: hsl(4, 87%, 34%);
--color-orange-900: hsl(4, 83%, 28%);
--color-orange-950: hsl(1, 89%, 15%);
/* colors */
--color-white: #fafafa;
--color-black: #12161d;
}
@supports (font-variation-settings: normal) {
:root {
font-family: InterVariable, sans-serif;
}
}
:root {
/* Typography*/
font-family: Inter, sans-serif;
font-feature-settings: "liga" 1, "calt" 1,
/* Contextual Alternates */ "dlig" 1, /* Discretionary Ligatures */ "ss07" 1,
/* fSquare punctuation */ "ss08" 1, /* Square quotes */ "zero" 1,
/* Slashed zero */ "tnum" 1, /* Tabular numbers */ "cv03" 1,
/* Open six */ "cv04" 1, /* Open nine */ "cv01" 1,
/* Alternate one */ "cv09", /* Flat-top three */ "cv02" 1; /* Open 4 */
/* style code blocks*/
}
.markdown-content {
@apply prose dark:prose-invert max-w-none font-mono;
}
/* Headings (Scaled Down & Responsive) */
.markdown-content h1 {
@apply text-xl font-medium mt-5 mb-3 md:mt-6 md:mb-4;
}
.markdown-content h2 {
@apply text-xs font-medium mt-4 mb-2 md:mt-5 md:mb-3;
}
.markdown-content h3 {
@apply text-sm font-medium mt-3 mb-1 md:mt-4 md:mb-3;
}
.markdown-content h4 {
@apply text-neutral-500 font-medium mt-3 mb-1 md:mt-4 md:mb-2;
}
.markdown-content h5 {
@apply text-sm font-medium mt-2 mb-1 md:mt-3 md:mb-2;
}
.markdown-content h6 {
@apply text-xs font-medium mt-2 mb-1 uppercase md:mt-3 md:mb-2;
}
/* Paragraphs */
.markdown-content p {
@apply text-neutral-500 leading-relaxed mb-3 md:mb-4;
}
/* Lists */
.markdown-content ul {
@apply list-disc list-inside ml-0 pl-0 md:ml-5;
}
.markdown-content li {
@apply text-neutral-500 leading-relaxed;
}
.markdown-content ol {
@apply list-decimal list-inside ml-3 md:ml-5;
}
/* Code Blocks */
.markdown-content pre {
@apply bg-gray-900 text-white p-2 rounded-md overflow-x-auto md:p-3;
}
.markdown-content code {
@apply bg-gray-800 text-xs p-1 rounded-md md:text-sm;
}
/* Links */
.markdown-content a {
@apply text-blue-600 hover:underline dark:text-blue-400;
}
/* Blockquotes */
.markdown-content blockquote {
@apply border-l-4 border-gray-500 pl-3 italic text-gray-600 md:pl-4;
}

5
public/js/cdn.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
public/js/flowbite.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -16,6 +16,10 @@ import StructuredData from './head/ArticleStructuredData.astro'
import Hreflang from '@/components/polymech/hreflang.astro'
import { IComponentConfig } from "@polymech/commons"
// Determine the path to your compiled Tailwind CSS.
// Assuming your built Tailwind CSS ends up in 'global.css' in your public directory after Astro build.
const tailwindCSSPath = "/global.css"; // <- **Important: Verify this path after your build process**
export interface Props {
title?: string;
meta_title?: string;
@ -132,11 +136,9 @@ const keywords = await item_keywords(item, Astro.currentLocale)
<link rel="preload" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap" as="style" />
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap" rel="stylesheet" media="print" onload="this.onload=null;this.removeAttribute('media');" />
<script src="/js/flowbite.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/flowbite@3.0.0/dist/flowbite.min.js" defer></script>
<!-- alpine JS -->
<script src="//unpkg.com/alpinejs" defer></script>
<script src="/js/cdn.min.js" defer></script>
<StructuredData frontmatter={item} />

View File

@ -1,12 +1,12 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
theme: {
extend: {},
},
daisyui: {
// Add your daisy ui themes here
themes: ["night"],
},
plugins: [require("daisyui"), require("@tailwindcss/typography")],
};
/** @type {import('tailwindcss').Config} */
export default {
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
theme: {
extend: {},
},
plugins: [require("@tailwindcss/typography")],
presets: [
]
}

File diff suppressed because one or more lines are too long