1

My goal is to create bookmarks section in NextJS application, where user can click "Add bookmark", type website address, and then favicon is fetched from that website, saved in local storage and displayed on website.

Favicon is saved in local storage properly, but when I try to display it on website it doesn't work and there are errors in console.

I tried different ways of creating image element and changing state but every time it shows similar result. I also tried different settings for CSP but without success.

In console it's either this

Security Error: Content at http://localhost:3000/ may not load data from blob:http://localhost:3000/fa614f8e-0ec6-48ef-ad52-0cce4f514d0e.

or this

GET blob:http://localhost:3000/4df97d52-2946-4389-97d5-7c734b706224 net::ERR_FILE_NOT_FOUND

File: SingleBookmark.tsx

const [faviconSource, setFaviconSource] = useState(null);

useEffect(() => {
  if (!localStorage.getItem(name)) {
    fetchFaviconToStorage();
  } else {
    setFaviconSource(JSON.parse(localStorage.getItem(name)));
  }
}, []);

const fetchFaviconToStorage = () => {
  const imgurl =
    `https://thingproxy.freeboard.io/fetch/http://${name}/favicon.ico`;
  fetch(imgurl)
    .then((response) => response.blob())
    .then((myBlob) => {
      const imageObjectURL = URL.createObjectURL(myBlob);
      localStorage.setItem(name, JSON.stringify(imageObjectURL));
      setFaviconSource(imageObjectURL);
    });
};

return (
<>
  {faviconSource &&
     <Image
         loader={(props) => imgixLoader(props, { fit: "crop", ar: "1:1" })}
         src={faviconSource}   
     />
  }
</>
);

File: next.config.js

const ContentSecurityPolicy = `
img-src 'self' data: blob:;
`;
const securityHeaders = [
  {
    key: "Content-Security-Policy",
    value: ContentSecurityPolicy.replace(/\s{2,}/g, " ").trim(),
  },
];

module.exports = {
  async headers() {
    return [
      {
        // Apply these headers to all routes in your application.
        source: "/:path*",
        headers: securityHeaders,
      },
    ];
  },
};
juliomalves
  • 42,130
  • 20
  • 150
  • 146
Fivis420
  • 11
  • 2
  • storing a `blob:` url in localStorage is basically useless: [from MDN](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL): "The URL lifetime is tied to the document in the window on which it was created". It will be invalidated as soon as you leave the page. Why don't you just do `` – Thomas Aug 25 '22 at 13:20
  • If I'll do that, after refreshing website favicons don't load quick enough and after website is loaded there is 0.5s lag before all bookmarks are fully loaded. That's why I wanted to cache it in local storage – Fivis420 Aug 25 '22 at 13:23
  • I'm not sure how to read the phrase "bookmarks fully loaded". imo. I find it perfectly fine for the favicons to pop-in next to the links. Especially if it's only half a second untill they're all there. I'd have an issue if the bookmarks wait and don't show for that period of time, just because they wait for the favicons to load. – Thomas Aug 25 '22 at 13:33
  • I've read about *(but I have no links at hand)*; you could use a service worker to cache the requests to `https://thingproxy.freeboard.io/fetch/http://${name}/favicon.ico` and store the images in the browsers cache. So you experience the delay only once, when you request the image for the first time (or the cache has been emptied). It was some article related to "offline first" apps. – Thomas Aug 25 '22 at 13:36

0 Answers0