require("@babel/register")({ presets: [ ["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-react", ], extensions: [".js", ".jsx"], ignore: [/node_modules/], }); // Minimal globals for socket.io-client only - no JSDOM to avoid interference global.window = {}; // Minimal window object for productCache global.navigator = { userAgent: "node.js" }; global.URL = require("url").URL; global.Blob = class MockBlob { constructor(data, options) { this.data = data; this.type = options?.type || ""; } }; // Import modules const fs = require("fs"); const path = require("path"); const React = require("react"); const io = require("socket.io-client"); // Initialize i18n for prerendering with German as default const i18n = require("i18next"); const { initReactI18next } = require("react-i18next"); // Import translation (just German for testing) const translationDE = require("./src/i18n/locales/de/translation.js").default; // Initialize i18n i18n .use(initReactI18next) .init({ resources: { de: { translation: translationDE } }, lng: 'de', fallbackLng: 'de', debug: false, interpolation: { escapeValue: false }, react: { useSuspense: false } }); // Make i18n available globally global.i18n = i18n; // Import prerender modules 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, saveProductImages } = require("./prerender/data-fetching.cjs"); // Import product component const PrerenderProduct = require("./src/PrerenderProduct.js").default; const renderSingleProduct = async (productSeoName) => { const socketUrl = "http://127.0.0.1:9303"; console.log(`šŸ”Œ Connecting to socket at ${socketUrl}...`); const socket = io(socketUrl, { path: "/socket.io/", transports: ["websocket"], reconnection: false, timeout: 10000, }); return new Promise((resolve, reject) => { const timeout = setTimeout(() => { console.error("āŒ Timeout: Could not connect to backend after 15 seconds"); socket.disconnect(); reject(new Error("Connection timeout")); }, 15000); socket.on("connect", async () => { console.log(`āœ… Socket connected. Fetching product: ${productSeoName}`); try { // Fetch product details const productDetails = await fetchProductDetails(socket, productSeoName); console.log(`šŸ“¦ Product found: ${productDetails.product.name}`); // Save product image to static files if (productDetails.product) { console.log(`šŸ“· Saving product image...`); await saveProductImages(socket, [productDetails.product], "Single Product", config.outputDir); } // Set up minimal global cache (empty for single product test) global.window.productCache = {}; global.productCache = {}; // Create product component const productComponent = React.createElement(PrerenderProduct, { productData: productDetails, t: global.i18n.t.bind(global.i18n), }); // Generate metadata const actualSeoName = productDetails.product.seoName || productSeoName; const filename = `Artikel/${actualSeoName}`; const location = `/Artikel/${actualSeoName}`; const description = `Product "${productDetails.product.name}" (seoName: ${productSeoName})`; const metaTags = generateProductMetaTags({ ...productDetails.product, seoName: actualSeoName, }, shopConfig.baseUrl, shopConfig); const jsonLdScript = generateProductJsonLd({ ...productDetails.product, seoName: actualSeoName, }, shopConfig.baseUrl, shopConfig); const combinedMetaTags = metaTags + "\n" + jsonLdScript; // Render the page console.log(`šŸŽØ Rendering product page...`); const success = renderPage( productComponent, location, filename, description, combinedMetaTags, true, // needsRouter config, false, // suppressLogs productDetails // productData for cache ); if (success) { const outputPath = path.resolve(__dirname, config.outputDir, `${filename}.html`); console.log(`āœ… Product page rendered successfully!`); console.log(`šŸ“„ Output file: ${outputPath}`); console.log(`🌐 Test URL: http://localhost:3000/Artikel/${actualSeoName}`); // Show file size if (fs.existsSync(outputPath)) { const stats = fs.statSync(outputPath); console.log(`šŸ“Š File size: ${Math.round(stats.size / 1024)}KB`); } } else { console.log(`āŒ Failed to render product page`); } clearTimeout(timeout); socket.disconnect(); resolve(success); } catch (error) { console.error(`āŒ Error fetching/rendering product: ${error.message}`); clearTimeout(timeout); socket.disconnect(); reject(error); } }); socket.on("connect_error", (err) => { clearTimeout(timeout); console.error("āŒ Socket connection error:", err); console.log("šŸ’” Make sure the backend server is running on http://127.0.0.1:9303"); reject(err); }); socket.on("error", (err) => { clearTimeout(timeout); console.error("āŒ Socket error:", err); reject(err); }); }); }; // Get product seoName from command line arguments const productSeoName = process.argv[2]; if (!productSeoName) { console.log("āŒ Usage: node prerender-single-product.cjs "); console.log("šŸ“ Example: node prerender-single-product.cjs led-grow-light-600w"); process.exit(1); } console.log(`šŸš€ Starting single product prerender test...`); console.log(`šŸŽÆ Product SEO name: ${productSeoName}`); console.log(`šŸ”§ Mode: ${config.isProduction ? 'PRODUCTION' : 'DEVELOPMENT'}`); console.log(`šŸ“ Output directory: ${config.outputDir}`); renderSingleProduct(productSeoName) .then((success) => { if (success) { console.log(`\nšŸŽ‰ Single product prerender completed successfully!`); process.exit(0); } else { console.log(`\nšŸ’„ Single product prerender failed!`); process.exit(1); } }) .catch((error) => { console.error(`\nšŸ’„ Single product prerender failed:`, error.message); process.exit(1); });