I am trying to implement the Highlight.js with my Next.js website’s blog page which is dynamically fetches data. All seems fine until I push it to production. In production it gives me client side error like :
“Application error: a client-side exception has occurred (see the browser console for more information).”
I can’t find a way how to fix it.
Images : https://imgur.com/a/W7FkxKg
import React, { useEffect, useState } from "react";
import mongoose from "mongoose";
import Blogs from "../../models/blogs";
import Head from "next/head";
import Comments from "@/components/commments";
import hljs from "highlight.js";
import "highlight.js/styles/atom-one-dark.css"; // You can choose any other style from highlight.js styles
const Blog = ({ blogs }) => {
const [mode, setMode] = useState(true);
const [isHljsApplied, setisHljsApplied] = useState(false);
useEffect(() => {
const darkMode = localStorage.getItem("darkMode");
setMode(darkMode === "true");
const codeBlocks = document.querySelectorAll("pre");
codeBlocks.forEach((codeBlock) => {
if (!codeBlock.parentNode.classList.contains("code-wrapper")) {
hljs.highlightElement(codeBlock);
const preWrapper = document.createElement("div");
preWrapper.className = "code-wrapper relative";
codeBlock.parentNode.insertBefore(preWrapper, codeBlock);
preWrapper.appendChild(codeBlock);
const copyButton = document.createElement("i");
copyButton.className =
"bg-gray-300 hover:bg-gray-400 transition duration-300 px-2 py-1 cursor-pointer rounded-md text-gray-600 copy-button absolute top-0 right-0 m-2 bx bx-copy";
copyButton.onclick = () =>
handleCopy(codeBlock.textContent.trim(), copyButton);
copyButton.textContent = "";
preWrapper.appendChild(copyButton);
}
});
// Add CSS class to paragraphs containing images
// const blogContent = document.querySelector(".ql-editor.blog");
// if (blogContent) {
// const paragraphs = blogContent.querySelectorAll("p");
// paragraphs.forEach((paragraph) => {
// if (paragraph.querySelector("img")) {
// paragraph.classList.add("flex", "justify-center");
// }
// });
// }
}, []);
const handleCopy = (code, copyButton) => {
navigator.clipboard.writeText(code).then(() => {
copyButton.classList.remove("bx-copy");
copyButton.textContent = "Copied!";
setTimeout(() => {
copyButton.textContent = "";
copyButton.classList.add("bx-copy");
}, 1000);
});
};
return (
<>
<Head>
<title>{blogs.title} | Soubhagyajit</title>
<script
async
src="https://www.won't_tell_you.com"
crossOrigin="anonymous"
></script>
<link rel="canonical" href={`https://www.soubhagyajit.com/blogs/${blogs.slug}`} />
<meta
name="description"
content={`${blogs.content.substring(3, 500)} . . .`}
/>
</Head>
{/* {!isHljsApplied && (<><div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 backdrop-blur-2xl">
<div className="bg-white p-4 rounded-lg">
<h2 className="text-xl text-red-500 mb-4 text-center">Caution!</h2>
<div className="flex justify-end text-center">
Something is blocked by your browser.<br/>Try disabling your adblocker.
</div>
</div>
</div></>)} */}
<main className={mode ? 'dark' : ''}>
<div className="pt-20 transition-all dark:bg-slate-900">
<div className="ml-[2%] sm:p-10 p-5 sm:mx-[5%] md:mx-[15%] lg:mx-[30%] sm:py-5 transition-all dark:text-white">
<h1 className="sm:text-5xl text-3xl font-bold">{blogs.title}</h1>
<p className="text-gray-500 my-5 text-[16px]">
<span className="flex items-center">
<div className="border-2 border-blue-600 w-fit rounded-full mr-2">
<img
className="object-cover rounded-full "
src="https://i.imgur.com/h1huc0w.png"
alt="Soubhagyajit Borah"
width={50}
/>
</div>
<span className="flex flex-col items-center">
Soubhagyajit Borah
<span className="text-gray-500 text-[16px]">
{new Date(blogs.createdAt).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})}
</span>
</span>
</span>
</p>
<hr className="border-none bg-slate-500 h-[1px] my-6" />
<div className="my-4 text-lg">
<div
className="blog"
dangerouslySetInnerHTML={{ __html: blogs.content }}
></div>
</div>
</div>
<Comments blogs={blogs} />
<style>
{`h1{
font-size:2rem;
}
h2{
font-size:1.5rem;
}
h3{
font-size:1.17rem;
}
.blog{
padding:0;
}
pre{
max-height:50vh;
border-radius: 3px;
background-color: #23241f;
overflow: auto;
}
pre.ql-syntax {
margin: 2px 0;
padding: 10px;
}
.blog a{
color:blue !important;
text-decoration: underline !important;
}
blockquote em{
margin: 0 10px;
}
blockquote {
font-size: 1.25em;
width: 100%;
margin: 64px auto;
font-family: Open Sans;
font-style: italic;
color: #555555;
padding: 1.2em 30px 1.2em 75px;
border-left: 6px solid lightgray;
line-height: 1.6;
position: relative;
background: ghostwhite;
border-radius: 4px;
}
.image-paragraph img {
max-width: 100%;
height: auto;
}
@media (prefers-color-scheme: dark) {
.blog a {
color: #58b1ff;
}
}
`}
</style>
</div>
</main>
</>
);
};
export async function getServerSideProps(context) {
if (!mongoose.connections[0].readyState) {
await mongoose.connect(process.env.MONGODB_URI);
}
const { slug } = context.query;
let blogs = null;
try {
blogs = await Blogs.findOne({ slug: slug });
} catch (error) {
console.error("Error fetching blog data:", error);
}
return {
props: { blogs: JSON.parse(JSON.stringify(blogs)) },
};
}
export default Blog;
I tried everything from placing console logs on some places, tried other libraries like Prism and react-syntax-highlight. Also tried to render the highlight function after proper loading of the page.