Advanced authentication at the Edge using Supabase & Next.JS
Applying httpOnly cookies to a Next.JS app using Supabase at the Edge
Sanna Jammeh
5/6/2022Using the next/image
component to generate blurred image placeholders serverside is an easy way to provide useful information to your users before the image manages to load. However, it is not always possible to generate a blurred image placeholder for every type of images. When you are dealing with dynamic data such as images from an external source, this process becomes very dificult.
This is a simple example of how to use the next/image
component to generate blurred image placeholders automatically.
import localImage from "public/localImage.png";
<Image src={localImage} placeholder="blur" />;
When a file is used as an image locally (i.e. not from an external source), the next/image
component will automatically generate a blurred image placeholder.
When using a local image, the next/image
component will automatically generate a blurred image placeholder. However, when using an external image or a local image as a string, the next/image
component will not generate a blurred image placeholder and requires the client to provide a blurred image placeholder using blurDataURL={'data:image/...'}
.
This makes fetching the blurred image placeholder very difficult. However, with a small amount of code, you can easily generate a blurred image placeholder for every type of image using sharp
.
sharp
to generate blurred placeholders on the serverHere is how it works
sharp
getStaticProps
or getServerSideProps
// utils/image.ts
const ROOT_PATH = process.cwd(); // The root path of the project
// Converts a buffer to a base64 data URL
const bufferToDataURL = (buffer: Buffer) => {
return `data:image/jpeg;base64,${buffer.toString("base64")}`;
};
export const getBlurDataURL = async (url: string) => {
let source: string | Buffer;
if (url.startsWith("http")) {
// Safe to assume this is an external image
source = Buffer.from(await (await fetch(url)).arrayBuffer());
} else {
source = path.join(ROOT_PATH, "public", url);
}
// Resize the image as small as possible per Vercel's recommendation
// I'm using 16:9 pixels as I know my images are using this ratio on the client
const image = await sharp(source)
.resize(16, 9, {
fit: "cover", // Resize the image to fit the ratio
})
.jpeg()
.toBuffer();
return bufferToDataURL(image);
};
// pages/index.tsx
export const getStaticProps = () => {
const data = await api.homePageData(); // Image url provided from external source or markdown file
return {
props: {
image: data.image,
blurDataURL: await getBlurDataURL(data.image),
},
};
};
interface HomeProps {
image: string;
blurDataURL: string;
}
const Home: NextPage<HomeProps> = ({ image, blurDataURL }) => {
return (
<div>
<Image src={image} placeholder="blur" blurDataURL={blurDataURL} />
</div>
);
};
export default Home;
There you go! Whenever you're fetching data from an external source, you can use getStaticProps
or getServerSideProps
to generate a blurred image placeholder.
Applying httpOnly cookies to a Next.JS app using Supabase at the Edge
Using Next.js + API Decorators - to quickly develop a RESTful API