diff --git a/components/ImageBox/ImageBox.jsx b/components/ImageBox/ImageBox.jsx
index 4c3381a..5cf4332 100644
--- a/components/ImageBox/ImageBox.jsx
+++ b/components/ImageBox/ImageBox.jsx
@@ -1,5 +1,5 @@
import Image from "next/image";
-import React from "react";
+import React, { useMemo } from "react";
import Styles from "./ImageBox.module.scss";
function ImageBox({
@@ -10,35 +10,47 @@ function ImageBox({
alt,
src,
style,
- layout,
+ layout = "fill",
aspectRatio,
+ priority = false,
+ quality = 75,
+ sizes,
...rest
}) {
- let dimensions = {};
- width ? (dimensions["width"] = width) : "100%";
- maxWidth ? (dimensions["maxWidth"] = maxWidth) : "100%";
- height ? (dimensions["height"] = height) : "unset";
- maxHeight ? (dimensions["maxHeight"] = maxHeight) : "unset";
+ const dimensions = useMemo(() => {
+ const dims = {};
+ if (width) dims.width = width;
+ if (maxWidth) dims.maxWidth = maxWidth;
+ if (height) dims.height = height;
+ if (maxHeight) dims.maxHeight = maxHeight;
+ return dims;
+ }, [width, maxWidth, height, maxHeight]);
+
+ const containerClass = aspectRatio ?
+ Styles.imageRatioContainer :
+ Styles.imageContainer;
+
+ const defaultSizes = sizes || "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw";
return (
-
+
);
}
-export default ImageBox;
+export default React.memo(ImageBox);
diff --git a/components/QuestionBox/QuestionBox.jsx b/components/QuestionBox/QuestionBox.jsx
index ebf9b5a..c414fbf 100644
--- a/components/QuestionBox/QuestionBox.jsx
+++ b/components/QuestionBox/QuestionBox.jsx
@@ -1,31 +1,44 @@
-import React, { useState } from "react";
+import React, { useState, useCallback, useMemo } from "react";
import Styles from "./QuestionBox.module.scss";
import { BiChevronRight, BiChevronDown } from "react-icons/bi";
function QuestionBox({ question }) {
const [isOpen, setIsOpen] = useState(false);
+
+ const toggleOpen = useCallback(() => {
+ setIsOpen(prev => !prev);
+ }, []);
+
+ const sanitizedAnswer = useMemo(() => {
+ return question?.attributes?.answer.replace(
+ /
-
>
);
}
-export default Metadata;
+export default React.memo(Metadata);
diff --git a/containers/EcosystemGrid/EcosystemGrid.jsx b/containers/EcosystemGrid/EcosystemGrid.jsx
index 5f45143..be64f69 100644
--- a/containers/EcosystemGrid/EcosystemGrid.jsx
+++ b/containers/EcosystemGrid/EcosystemGrid.jsx
@@ -1,10 +1,10 @@
-import React, { useState, useContext } from "react";
+import React, { useState, useContext, useMemo, useCallback } from "react";
import styles from "./EcosystemGrid.module.scss";
import { RiTwitterXLine } from "react-icons/ri";
import { FaTelegramPlane } from "react-icons/fa";
import { SlGlobe } from "react-icons/sl";
import ThemeContext from "../../utils/services/Themecontext";
-import { ImageBox } from "../../components";
+import ImageBox from "../../components/ImageBox/ImageBox";
const badgeOptions = [
"Artificial Intelligence (AI)",
@@ -391,10 +391,20 @@ const ecosystemData = [
const EcosystemGrid = () => {
const [activeTag, setActiveTag] = useState("Artificial Intelligence (AI)");
- const filtered = ecosystemData.filter((item) =>
- item.tags.includes(activeTag)
+ const { theme } = useContext(ThemeContext);
+
+ const filtered = useMemo(() =>
+ ecosystemData.filter(item => item.tags.includes(activeTag)),
+ [activeTag]
);
- const { theme, setTheme } = useContext(ThemeContext);
+
+ const handleTagClick = useCallback((tag) => {
+ setActiveTag(tag);
+ }, []);
+
+ const imageStyle = useMemo(() => ({
+ filter: theme === "dark" ? "brightness(100%)" : "brightness(10%)"
+ }), [theme]);
return (
@@ -402,10 +412,9 @@ const EcosystemGrid = () => {
{badgeOptions.map((tag) => (
@@ -416,39 +425,24 @@ const EcosystemGrid = () => {
{filtered
.filter((item) => item.image)
.map((item, idx) => (
-
+
- {/*

*/}
-
-
+
-
{item.description}
{
);
};
-export default EcosystemGrid;
+export default React.memo(EcosystemGrid);
diff --git a/containers/index.js b/containers/index.js
index eb3e590..2e17ba7 100644
--- a/containers/index.js
+++ b/containers/index.js
@@ -39,10 +39,16 @@ export const HoverContainer = dynamic(() =>
import("./HoverContainer/HoverContainer")
);
export const LighthouseSuit = dynamic(() =>
- import("./LighthouseSuit/LighthouseSuit")
+ import("./LighthouseSuit/LighthouseSuit"), {
+ loading: () => Loading...
,
+ ssr: true
+ }
);
export const Pricing = dynamic(() =>
- import("./Pricing/Pricing")
+ import("./Pricing/Pricing"), {
+ loading: () => Loading...
,
+ ssr: true
+ }
);
export const EcosystemBanner = dynamic(() =>
import("./EcosystemBanner/EcosystemBanner")
diff --git a/next.config.js b/next.config.js
index a8fdd55..dab7c86 100644
--- a/next.config.js
+++ b/next.config.js
@@ -9,6 +9,23 @@ const nextConfig = {
"gateway.lighthouse.storage",
"cms.lighthouse.storage",
],
+ formats: ['image/avif', 'image/webp'],
+ minimumCacheTTL: 60,
+ },
+ experimental: {
+ optimizeCss: true,
+ scrollRestoration: true,
+ },
+ compiler: {
+ removeConsole: process.env.NODE_ENV === 'production',
+ },
+ webpack: (config, { dev, isServer }) => {
+ config.optimization = {
+ ...config.optimization,
+ usedExports: true,
+ sideEffects: true,
+ }
+ return config
},
};
diff --git a/package.json b/package.json
index c5c94e0..ac611b1 100644
--- a/package.json
+++ b/package.json
@@ -6,27 +6,26 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
- "lint": "next lint"
+ "lint": "next lint",
+ "analyze": "ANALYZE=true next build"
},
"dependencies": {
"aos": "^2.3.4",
"axios": "^1.1.3",
- "lighthouse_ui_2.0": "file:",
- "next": "12.3.1",
+ "next": "^12.3.1",
"react": "18.2.0",
"react-countup": "^6.5.0",
"react-dom": "18.2.0",
"react-icons": "^4.7.1",
"react-markdown": "^8.0.5",
"react-paginate": "^8.1.4",
- "react-pagination": "^1.0.0",
"react-toastify": "^9.1.1",
"react-tooltip": "^5.28.0",
- "rfs": "^10.0.0",
"sass": "^1.55.0",
"swiper": "^8.4.7"
},
"devDependencies": {
+ "@next/bundle-analyzer": "^12.3.1",
"eslint": "8.25.0",
"eslint-config-next": "12.3.1"
}
diff --git a/pages/_app.js b/pages/_app.js
index 03befd5..ce806f3 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -3,8 +3,6 @@ import "../styles/globals.scss";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
-import AOS from "aos";
-import "aos/dist/aos.css";
import { useEffect, useState } from "react";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
@@ -15,36 +13,45 @@ function MyApp({ Component, pageProps }) {
const [theme, setTheme] = useState(null);
useEffect(() => {
- AOS.init({
- disable: false,
- startEvent: "DOMContentLoaded",
- initClassName: "aos-init",
- animatedClassName: "aos-animate",
- useClassNames: false,
- disableMutationObserver: false,
- debounceDelay: 50,
- throttleDelay: 99,
+ const initAOS = async () => {
+ if (typeof window !== 'undefined') {
+ const AOS = (await import('aos')).default;
+ await import('aos/dist/aos.css');
+
+ AOS.init({
+ disable: false,
+ startEvent: "DOMContentLoaded",
+ initClassName: "aos-init",
+ animatedClassName: "aos-animate",
+ useClassNames: false,
+ disableMutationObserver: false,
+ debounceDelay: 50,
+ throttleDelay: 99,
+ offset: 120,
+ delay: 0,
+ duration: 400,
+ easing: "ease",
+ once: true,
+ mirror: false,
+ anchorPlacement: "top-center",
+ });
+ }
+ };
- offset: 120,
- delay: 0,
- duration: 400,
- easing: "ease",
- once: true,
- mirror: false,
- anchorPlacement: "top-center",
- });
- const themeFromLocalStorage = JSON.parse(
- localStorage?.getItem("lighthouse.storage/store") || "{}"
- );
- if (themeFromLocalStorage?.theme) {
- setTheme(themeFromLocalStorage?.theme);
- } else {
- setTheme("dark");
+ initAOS();
+
+ if (typeof window !== 'undefined') {
+ const themeFromLocalStorage = JSON.parse(
+ localStorage?.getItem("lighthouse.storage/store") || "{}"
+ );
+ setTheme(themeFromLocalStorage?.theme || "dark");
}
}, []);
useEffect(() => {
- themeChanger(theme);
+ if (theme) {
+ themeChanger(theme);
+ }
}, [theme]);
return (
diff --git a/pages/blogs/index.js b/pages/blogs/index.js
index 3bfdf9a..f381128 100644
--- a/pages/blogs/index.js
+++ b/pages/blogs/index.js
@@ -1,5 +1,5 @@
import axios from "axios";
-import React, { useEffect, useState } from "react";
+import React from "react";
import { Metadata } from "../../components";
import {
FeaturedArticle,
@@ -14,19 +14,30 @@ export const getStaticProps = async () => {
try {
const res = await axios.get(`${baseUrl}/blogs?pagination[pageSize]=50&populate=*`);
blogsData = res["status"] === 200 ? res["data"]?.["data"] : null;
- console.log(blogsData);
- } catch (error) {}
+ } catch (error) {
+ console.error("Error fetching blogs:", error);
+ }
+
return {
props: {
- blogsData,
+ blogsData: blogsData || [],
},
+ revalidate: 3600,
+ notFound: !blogsData,
};
};
function Blogs({ blogsData }) {
+ if (!blogsData) {
+ return Loading...
;
+ }
+
return (
<>
-
+
diff --git a/utils/services/theme.js b/utils/services/theme.js
index 36ee513..900781f 100644
--- a/utils/services/theme.js
+++ b/utils/services/theme.js
@@ -42,12 +42,24 @@ const ThemeProperties = [
];
export const themeChanger = (theme) => {
- theme &&
- localStorage.setItem("lighthouse.storage/store", JSON.stringify({ theme }));
- ThemeProperties.forEach((property) => {
- document.documentElement.style.setProperty(
- `${property?.property}`,
- theme === "dark" ? property?.dark : property?.light
- );
- });
+ if (!theme || typeof window === 'undefined') return;
+
+ try {
+ requestAnimationFrame(() => {
+ localStorage.setItem(
+ "lighthouse.storage/store",
+ JSON.stringify({ theme })
+ );
+
+ const style = document.documentElement.style;
+ ThemeProperties.forEach((property) => {
+ style.setProperty(
+ property.property,
+ theme === "dark" ? property.dark : property.light
+ );
+ });
+ });
+ } catch (error) {
+ console.error('Error updating theme:', error);
+ }
};