diff --git a/prerender-single-product.cjs b/prerender-single-product.cjs
index 9788079..802c404 100644
--- a/prerender-single-product.cjs
+++ b/prerender-single-product.cjs
@@ -57,7 +57,7 @@ const config = require("./prerender/config.cjs");
const shopConfig = require("./src/config.js").default;
const { renderPage } = require("./prerender/renderer.cjs");
const { generateProductMetaTags, generateProductJsonLd } = require("./prerender/seo.cjs");
-const { fetchProductDetails } = require("./prerender/data-fetching.cjs");
+const { fetchProductDetails, saveProductImages } = require("./prerender/data-fetching.cjs");
// Import product component
const PrerenderProduct = require("./src/PrerenderProduct.js").default;
diff --git a/prerender/renderer.cjs b/prerender/renderer.cjs
index 07aac0e..42e7d99 100644
--- a/prerender/renderer.cjs
+++ b/prerender/renderer.cjs
@@ -178,11 +178,16 @@ const renderPage = (
const prerenderFallbackScript = `
`;
@@ -239,8 +244,10 @@ const renderPage = (
let newHtml;
if (rootDivRegex.test(template)) {
+ if (!suppressLogs) console.log(` 📝 Root div found, replacing with ${renderedMarkup.length} chars of markup`);
newHtml = template.replace(rootDivRegex, replacementHtml);
} else {
+ if (!suppressLogs) console.log(` ⚠️ No root div found, appending to body`);
newHtml = template.replace("
", `${replacementHtml}`);
}
diff --git a/src/App.js b/src/App.js
index bc928fe..65b7884 100644
--- a/src/App.js
+++ b/src/App.js
@@ -32,11 +32,15 @@ import Header from "./components/Header.js";
import Footer from "./components/Footer.js";
import MainPageLayout from "./components/MainPageLayout.js";
-// Lazy load all route components to reduce initial bundle size
-const Content = lazy(() => import(/* webpackChunkName: "content" */ "./components/Content.js"));
-const ProductDetailWithSocket = lazy(() => import(/* webpackChunkName: "product-detail" */ "./components/ProductDetailWithSocket.js"));
-const ProfilePageWithSocket = lazy(() => import(/* webpackChunkName: "profile" */ "./pages/ProfilePage.js"));
-const ResetPassword = lazy(() => import(/* webpackChunkName: "reset-password" */ "./pages/ResetPassword.js"));
+// TEMPORARILY DISABLE ALL LAZY LOADING TO ELIMINATE CircularProgress
+import Content from "./components/Content.js";
+import ProductDetailWithSocket from "./components/ProductDetailWithSocket.js";
+import ProfilePageWithSocket from "./pages/ProfilePage.js";
+import ResetPassword from "./pages/ResetPassword.js";
+// const Content = lazy(() => import(/* webpackChunkName: "content" */ "./components/Content.js"));
+// const ProductDetailWithSocket = lazy(() => import(/* webpackChunkName: "product-detail" */ "./components/ProductDetailWithSocket.js"));
+// const ProfilePageWithSocket = lazy(() => import(/* webpackChunkName: "profile" */ "./pages/ProfilePage.js"));
+// const ResetPassword = lazy(() => import(/* webpackChunkName: "reset-password" */ "./pages/ResetPassword.js"));
// Lazy load admin pages - only loaded when admin users access them
const AdminPage = lazy(() => import(/* webpackChunkName: "admin" */ "./pages/AdminPage.js"));
@@ -201,16 +205,25 @@ const AppContent = ({ currentTheme, onThemeChange }) => {
-
-
+ // Use prerender fallback if available, otherwise show loading spinner
+ typeof window !== "undefined" && window.__PRERENDER_FALLBACK__ ? (
+
+ ) : (
+
+
+
+ )
}>
@@ -280,7 +293,17 @@ const AppContent = ({ currentTheme, onThemeChange }) => {
{/* Conditionally render the Chat Assistant */}
{isChatOpen && (
- }>
+
+ ) : (
+
+ )
+ }>
{
{/* Development-only Theme Customizer Dialog */}
{isDevelopment && isThemeCustomizerOpen && (
- }>
+
+ ) : (
+
+ )
+ }>
setThemeCustomizerOpen(false)}
@@ -382,16 +415,24 @@ const App = () => {
-
-
+ typeof window !== "undefined" && window.__PRERENDER_FALLBACK__ ? (
+
+ ) : (
+
+
+
+ )
}
>
{
if(res.success){
window.tinyPicCache[picid] = URL.createObjectURL(new Blob([res.imageBuffer], { type: 'image/jpeg' }));
diff --git a/src/components/Images.js b/src/components/Images.js
index baca1b9..5a25788 100644
--- a/src/components/Images.js
+++ b/src/components/Images.js
@@ -12,7 +12,7 @@ import LoupeIcon from '@mui/icons-material/Loupe';
class Images extends Component {
constructor(props) {
super(props);
- this.state = { mainPic:0,pics:[]};
+ this.state = { mainPic:0,pics:[], needsSocketRetry: false };
}
componentDidMount () {
@@ -22,6 +22,15 @@ class Images extends Component {
if (prevProps.fullscreenOpen !== this.props.fullscreenOpen) {
this.updatePics();
}
+
+ // Retry loading images if socket just became available
+ const wasConnected = prevProps.socketB && prevProps.socketB.connected;
+ const isNowConnected = this.props.socketB && this.props.socketB.connected;
+
+ if (!wasConnected && isNowConnected && this.state.needsSocketRetry) {
+ this.setState({ needsSocketRetry: false });
+ this.updatePics();
+ }
}
updatePics = (newMainPic = this.state.mainPic) => {
@@ -49,10 +58,10 @@ class Images extends Component {
pics.push(window.smallPicCache[bildId]);
this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic);
}else if(window.tinyPicCache[bildId]){
- pics.push(bildId);
+ pics.push(window.tinyPicCache[bildId]);
this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic);
}else{
- pics.push(bildId);
+ pics.push(`/assets/images/prod${bildId}.jpg`);
this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic);
}
}else{
@@ -67,7 +76,8 @@ class Images extends Component {
}
}
}
- console.log('pics',pics);
+ console.log('DEBUG: pics array contents:', pics);
+ console.log('DEBUG: pics array types:', pics.map(p => typeof p + ': ' + p));
this.setState({ pics, mainPic: newMainPic });
}else{
if(this.state.pics.length > 0) this.setState({ pics:[], mainPic: newMainPic });
@@ -75,6 +85,13 @@ class Images extends Component {
}
loadPic = (size,bildId,index) => {
+ // Check if socketB is available and connected before emitting
+ if (!this.props.socketB || !this.props.socketB.connected) {
+ console.log("Images: socketB not available, will retry when connected");
+ this.setState({ needsSocketRetry: true });
+ return;
+ }
+
this.props.socketB.emit('getPic', { bildId, size }, (res) => {
if(res.success){
const url = URL.createObjectURL(new Blob([res.imageBuffer], { type: 'image/jpeg' }));
diff --git a/src/components/Product.js b/src/components/Product.js
index afcc304..a6a0afd 100644
--- a/src/components/Product.js
+++ b/src/components/Product.js
@@ -28,25 +28,16 @@ class Product extends Component {
}else{
this.state = {image: null, loading: true, error: false};
console.log("Product: Fetching image from socketB", this.props.socketB);
- this.props.socketB.emit('getPic', { bildId, size:'small' }, (res) => {
- if(res.success){
- window.smallPicCache[bildId] = URL.createObjectURL(new Blob([res.imageBuffer], { type: 'image/jpeg' }));
- if (this._isMounted) {
- this.setState({image: window.smallPicCache[bildId], loading: false});
- } else {
- this.state.image = window.smallPicCache[bildId];
- this.state.loading = false;
- }
- }else{
- console.log('Fehler beim Laden des Bildes:', res);
- if (this._isMounted) {
- this.setState({error: true, loading: false});
- } else {
- this.state.error = true;
- this.state.loading = false;
- }
- }
- })
+
+ // Check if socketB is available and connected before emitting
+ if (this.props.socketB && this.props.socketB.connected) {
+ this.loadImage(bildId);
+ } else {
+ // Socket not available, set error state or wait
+ console.log("Product: socketB not available, will retry when connected");
+ this.state.error = true;
+ this.state.loading = false;
+ }
}
}else{
this.state = {image: null, loading: false, error: false};
@@ -57,6 +48,45 @@ class Product extends Component {
this._isMounted = true;
}
+ componentDidUpdate(prevProps) {
+ // Retry loading image if socket just became available
+ const wasConnected = prevProps.socketB && prevProps.socketB.connected;
+ const isNowConnected = this.props.socketB && this.props.socketB.connected;
+
+ if (!wasConnected && isNowConnected && this.state.error && this.props.pictureList) {
+ // Socket just connected and we had an error, retry loading
+ const bildId = this.props.pictureList.split(',')[0];
+ if (!window.smallPicCache[bildId]) {
+ this.setState({loading: true, error: false});
+ this.loadImage(bildId);
+ }
+ }
+ }
+
+ loadImage = (bildId) => {
+ if (this.props.socketB && this.props.socketB.connected) {
+ this.props.socketB.emit('getPic', { bildId, size:'small' }, (res) => {
+ if(res.success){
+ window.smallPicCache[bildId] = URL.createObjectURL(new Blob([res.imageBuffer], { type: 'image/jpeg' }));
+ if (this._isMounted) {
+ this.setState({image: window.smallPicCache[bildId], loading: false});
+ } else {
+ this.state.image = window.smallPicCache[bildId];
+ this.state.loading = false;
+ }
+ }else{
+ console.log('Fehler beim Laden des Bildes:', res);
+ if (this._isMounted) {
+ this.setState({error: true, loading: false});
+ } else {
+ this.state.error = true;
+ this.state.loading = false;
+ }
+ }
+ });
+ }
+ }
+
componentWillUnmount() {
this._isMounted = false;
}
diff --git a/src/components/ProductDetailPage.js b/src/components/ProductDetailPage.js
index 1041485..eaa6396 100644
--- a/src/components/ProductDetailPage.js
+++ b/src/components/ProductDetailPage.js
@@ -356,7 +356,6 @@ class ProductDetailPage extends Component {
if (!this.props.socket || !this.props.socket.connected) {
// Socket not connected yet, but don't show error immediately on first load
// The componentDidUpdate will retry when socket connects
- console.log("Socket not connected yet, waiting for connection to load product data");
return;
}
@@ -538,11 +537,27 @@ class ProductDetailPage extends Component {
}
};
- render() {
+ render() {
const { product, loading, error, attributeImages, isSteckling, attributes, komponentenLoaded, komponentenData, komponentenImages, totalKomponentenPrice, totalSavings } =
this.state;
+ // Debug alerts removed
+
+
+
if (loading) {
+ // Check if prerender fallback is available
+ if (typeof window !== "undefined" && window.__PRERENDER_FALLBACK__) {
+ return (
+
+ );
+ }
+
+ // Fallback to loading message if no prerender content
return (
{
),
endAdornment: (
- {loadingSuggestions && }
+ {loadingSuggestions && }