feat: optimize image loading and critical rendering path by adding image preloads in webpack config, updating image handling in multiple components, and ensuring alt attributes are set for accessibility
This commit is contained in:
@@ -634,12 +634,26 @@ class Content extends Component {
|
|||||||
<Box sx={{
|
<Box sx={{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
bgcolor: '#e1f0d3',
|
bgcolor: '#e1f0d3',
|
||||||
backgroundImage: 'url("/assets/images/seeds.jpg")',
|
position: 'relative',
|
||||||
backgroundSize: 'contain',
|
display: 'flex',
|
||||||
backgroundPosition: 'center',
|
alignItems: 'center',
|
||||||
backgroundRepeat: 'no-repeat',
|
justifyContent: 'center'
|
||||||
position: 'relative'
|
|
||||||
}}>
|
}}>
|
||||||
|
<img
|
||||||
|
src="/assets/images/seeds.jpg"
|
||||||
|
alt="Seeds"
|
||||||
|
fetchPriority="high"
|
||||||
|
loading="eager"
|
||||||
|
style={{
|
||||||
|
maxWidth: '100%',
|
||||||
|
maxHeight: '100%',
|
||||||
|
objectFit: 'contain',
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{/* Overlay text - optional */}
|
{/* Overlay text - optional */}
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@@ -681,12 +695,26 @@ class Content extends Component {
|
|||||||
<Box sx={{
|
<Box sx={{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
bgcolor: '#e8f5d6',
|
bgcolor: '#e8f5d6',
|
||||||
backgroundImage: 'url("/assets/images/cutlings.jpg")',
|
position: 'relative',
|
||||||
backgroundSize: 'contain',
|
display: 'flex',
|
||||||
backgroundPosition: 'center',
|
alignItems: 'center',
|
||||||
backgroundRepeat: 'no-repeat',
|
justifyContent: 'center'
|
||||||
position: 'relative'
|
|
||||||
}}>
|
}}>
|
||||||
|
<img
|
||||||
|
src="/assets/images/cutlings.jpg"
|
||||||
|
alt="Stecklinge"
|
||||||
|
fetchPriority="high"
|
||||||
|
loading="eager"
|
||||||
|
style={{
|
||||||
|
maxWidth: '100%',
|
||||||
|
maxHeight: '100%',
|
||||||
|
objectFit: 'contain',
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{/* Overlay text - optional */}
|
{/* Overlay text - optional */}
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ class Images extends Component {
|
|||||||
component="img"
|
component="img"
|
||||||
height="400"
|
height="400"
|
||||||
image={getImagePath(this.props.pictureList)}
|
image={getImagePath(this.props.pictureList)}
|
||||||
|
alt={this.props.productName || 'Produktbild'}
|
||||||
fetchPriority="high"
|
fetchPriority="high"
|
||||||
loading="eager"
|
loading="eager"
|
||||||
sx={{
|
sx={{
|
||||||
@@ -174,6 +175,7 @@ class Images extends Component {
|
|||||||
height="400"
|
height="400"
|
||||||
fetchPriority="high"
|
fetchPriority="high"
|
||||||
loading="eager"
|
loading="eager"
|
||||||
|
alt={this.props.productName || 'Produktbild'}
|
||||||
sx={{
|
sx={{
|
||||||
objectFit: 'contain',
|
objectFit: 'contain',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
@@ -236,6 +238,7 @@ class Images extends Component {
|
|||||||
<CardMedia
|
<CardMedia
|
||||||
component="img"
|
component="img"
|
||||||
height="80"
|
height="80"
|
||||||
|
alt={`${this.props.productName || 'Produktbild'} - Bild ${originalIndex + 1}`}
|
||||||
sx={{
|
sx={{
|
||||||
objectFit: 'contain',
|
objectFit: 'contain',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
@@ -308,6 +311,7 @@ class Images extends Component {
|
|||||||
{this.state.pics[this.state.mainPic] && (
|
{this.state.pics[this.state.mainPic] && (
|
||||||
<CardMedia
|
<CardMedia
|
||||||
component="img"
|
component="img"
|
||||||
|
alt={this.props.productName || 'Produktbild'}
|
||||||
sx={{
|
sx={{
|
||||||
objectFit: 'contain',
|
objectFit: 'contain',
|
||||||
width: '90vw',
|
width: '90vw',
|
||||||
@@ -361,6 +365,7 @@ class Images extends Component {
|
|||||||
<CardMedia
|
<CardMedia
|
||||||
component="img"
|
component="img"
|
||||||
height="60"
|
height="60"
|
||||||
|
alt={`${this.props.productName || 'Produktbild'} - Miniaturansicht ${originalIndex + 1}`}
|
||||||
sx={{
|
sx={{
|
||||||
objectFit: 'contain',
|
objectFit: 'contain',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
|
|||||||
@@ -606,13 +606,27 @@ const MainPageLayout = () => {
|
|||||||
sx={{
|
sx={{
|
||||||
height: "100%",
|
height: "100%",
|
||||||
bgcolor: box.bgcolor,
|
bgcolor: box.bgcolor,
|
||||||
backgroundImage: `url("${box.image}")`,
|
|
||||||
backgroundSize: "contain",
|
|
||||||
backgroundPosition: "center",
|
|
||||||
backgroundRepeat: "no-repeat",
|
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<img
|
||||||
|
src={box.image}
|
||||||
|
alt={box.title}
|
||||||
|
fetchPriority="high"
|
||||||
|
loading="eager"
|
||||||
|
style={{
|
||||||
|
maxWidth: "100%",
|
||||||
|
maxHeight: "100%",
|
||||||
|
objectFit: "contain",
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ const ProductImage = ({
|
|||||||
socket={socket}
|
socket={socket}
|
||||||
socketB={socketB}
|
socketB={socketB}
|
||||||
pictureList={product.pictureList}
|
pictureList={product.pictureList}
|
||||||
|
productName={product.name}
|
||||||
fullscreenOpen={fullscreenOpen}
|
fullscreenOpen={fullscreenOpen}
|
||||||
onOpenFullscreen={onOpenFullscreen}
|
onOpenFullscreen={onOpenFullscreen}
|
||||||
onCloseFullscreen={onCloseFullscreen}
|
onCloseFullscreen={onCloseFullscreen}
|
||||||
|
|||||||
@@ -161,14 +161,32 @@ class InlineCssPlugin {
|
|||||||
fontPreloads += `<link rel="preload" href="${fontUrl}" as="font" type="font/truetype" crossorigin>\n`;
|
fontPreloads += `<link rel="preload" href="${fontUrl}" as="font" type="font/truetype" crossorigin>\n`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add critical image preloads for LCP optimization
|
||||||
|
const criticalImages = [
|
||||||
|
'/assets/images/filiale1.jpg',
|
||||||
|
'/assets/images/filiale2.jpg',
|
||||||
|
'/assets/images/seeds.jpg',
|
||||||
|
'/assets/images/cutlings.jpg',
|
||||||
|
'/assets/images/presse.jpg',
|
||||||
|
'/assets/images/purpl.jpg'
|
||||||
|
];
|
||||||
|
|
||||||
|
let imagePreloads = '';
|
||||||
|
criticalImages.forEach(imagePath => {
|
||||||
|
imagePreloads += `<link rel="preload" href="${imagePath}" as="image">\n`;
|
||||||
|
});
|
||||||
|
|
||||||
// Add inlined CSS to head
|
// Add inlined CSS to head
|
||||||
const styleTag = `<style type="text/css">${inlinedCss.trim()}</style>`;
|
const styleTag = `<style type="text/css">${inlinedCss.trim()}</style>`;
|
||||||
data.html = data.html.replace('</head>', `${fontPreloads}${styleTag}\n</head>`);
|
data.html = data.html.replace('</head>', `${fontPreloads}${imagePreloads}${styleTag}\n</head>`);
|
||||||
|
|
||||||
console.log(`✅ Inlined CSS assets: ${cssAssets.join(', ')} (${Math.round(inlinedCss.length / 1024)}KB)`);
|
console.log(`✅ Inlined CSS assets: ${cssAssets.join(', ')} (${Math.round(inlinedCss.length / 1024)}KB)`);
|
||||||
if (fontUrls.length > 0) {
|
if (fontUrls.length > 0) {
|
||||||
console.log(`✅ Added font preloads: ${fontUrls.length} fonts`);
|
console.log(`✅ Added font preloads: ${fontUrls.length} fonts`);
|
||||||
}
|
}
|
||||||
|
if (criticalImages.length > 0) {
|
||||||
|
console.log(`✅ Added image preloads: ${criticalImages.length} critical images`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(null, data);
|
cb(null, data);
|
||||||
|
|||||||
Reference in New Issue
Block a user