Next.js App Router Customer Image Component
vader1359 opened this issue · 3 comments
vader1359 commented
I switch to AppRouter and using the "use client" for the NotionPage. The page rendered correctly but no matter what I try, the images are not optimized.
I both tried using the next/image, passing nextImage to the custom component prop
I also create a Cloudinary Image Component and pass to the customer component prop
It does not work.
Anyone have the similar issue?
Test Notion Page: https://www.notion.so/iant1359/About-Us-ea21588ce29b43038e42c7979d715b7d
My code:
// core styles shared by all of react-notion-x (required)
import 'react-notion-x/src/styles.css'
import * as React from 'react'
import dynamic from 'next/dynamic'
import Head from 'next/head'
import Image from 'next/image'
import Link from 'next/link'
// import { useRouter } from 'next/router'
import { ExtendedRecordMap } from 'notion-types'
import { getPageTitle } from 'notion-utils'
import { NotionRenderer } from 'react-notion-x'
import {CldImageProps} from "next-cloudinary"
import CldImage from './CldImage'
// import TweetEmbed from 'react-tweet-embed'
// -----------------------------------------------------------------------------
// dynamic imports for optional components
// -----------------------------------------------------------------------------
const Collection = dynamic(() =>
import('react-notion-x/build/third-party/collection').then(m => m.Collection),
)
// Extend the props for your ImageComponent
interface ImageComponentProps extends CldImageProps {
// Add any additional props here if needed
}
const ImageComponent: React.FC<ImageComponentProps> = (props) => (
<CldImage
{...props}
width={2048}
height={1600}
alt="illustration image for doc"
deliveryType="fetch"
dpr="auto"
config={{ cloud: { cloudName: 'iant1359' } }}
/>
);
const NotionPage = ({
recordMap,
previewImagesEnabled,
rootPageId,
rootDomain,
}: {
recordMap: ExtendedRecordMap
previewImagesEnabled?: boolean
rootPageId?: string
rootDomain?: string
}) => {
// const router = useRouter()
// if (router.isFallback) {
// return <Loading />
// }
if (!recordMap) {
return null
}
const title = getPageTitle(recordMap)
// useful for debugging from the dev console
if (typeof window !== 'undefined') {
const keys = Object.keys(recordMap?.block || {})
const block = recordMap?.block?.[keys[0]]?.value
const g = window as any
g.recordMap = recordMap
g.block = block
}
const socialDescription = 'React Notion X Demo'
const socialImage =
'https://react-notion-x-demo.transitivebullsh.it/social.jpg'
return (
<>
<Head>
{socialDescription && (
<>
<meta name="description" content={socialDescription} />
<meta property="og:description" content={socialDescription} />
<meta name="twitter:description" content={socialDescription} />
</>
)}
{socialImage ? (
<>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={socialImage} />
<meta property="og:image" content={socialImage} />
</>
) : (
<meta name="twitter:card" content="summary" />
)}
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="twitter:title" content={title} />
<meta name="twitter:creator" content="@transitive_bs" />
<link rel="icon" href="/favicon.ico" />
</Head>
<NotionRenderer
recordMap={recordMap}
fullPage
darkMode={false}
rootDomain={rootDomain}
rootPageId={rootPageId}
previewImages={previewImagesEnabled}
components={{
// NOTE (transitive-bullshit 3/12/2023): I'm disabling next/image for this repo for now because the amount of traffic started costing me hundreds of dollars a month in Vercel image optimization costs. I'll probably re-enable it in the future if I can find a better solution.
nextImage: ImageComponent,
nextLink: Link,
// Collection,
}}
// NOTE: custom images will only take effect if previewImages is true and
// if the image has a valid preview image defined in recordMap.preview_images[src]
/>
</>
)
}
export default NotionPage
import { ExtendedRecordMap, SearchParams, SearchResults } from 'notion-types';
import { previewImagesEnabled } from './config';
// Type definition for the image map (if not already defined)
interface PreviewImageMap {
[key: string]: string;
}
async function getPreviewImageMap(recordMap: ExtendedRecordMap): Promise<PreviewImageMap> {
const previewImageMap: PreviewImageMap = {};
const blocks = recordMap.block;
if (blocks) {
Object.keys(blocks).forEach(blockId => {
const block = blocks[blockId].value;
if (block && block.type === 'image' && block.properties && block.properties.source) {
const imageUrl = block.properties.source[0][0] as string; // Assuming source is stored this way
previewImageMap[blockId] = transformImageURLToPreview(imageUrl);
}
});
}
return previewImageMap;
}
const notion = new NotionAPI();
export async function getPage(pageId: string): Promise<ExtendedRecordMap> {
const recordMap = await notion.getPage(pageId);
if (!recordMap) {
throw new Error('Failed to retrieve the page data from Notion');
}
if (previewImagesEnabled && recordMap) {
try {
const previewImageMap = await getPreviewImageMap(recordMap);
(recordMap as any).preview_images = previewImageMap;
} catch (error) {
console.error('Error fetching preview images:', error);
throw new Error('Error processing preview images');
}
}
console.log(recordMap)
return recordMap;
}
export async function search(params: SearchParams): Promise<SearchResults> {
return notion.search(params);
}
function transformImageURLToPreview(url: string): string {
return url.replace('original', 'preview');
}
4anghyeon commented
this way worked for me.
function NextImageComponent(props: ImageProps) {
return (
<Image
{...props}
width={400}
height={400}
// loading={"eager"}
></Image>
);
}
function NotionContainer() {
return (
<NotionRenderer
...
forceCustomImages={true}
components={{
Image: NextImageComponent,
nextLink: Link,
}}
/>
);
}