Magnolia CMS NextJS混合SSG开发:组件如何获取内容类型数据?
在Magnolia CMS + Next.js混合SSG项目中实现内容类型列表组件的方案
方案1:组件内直接调用Magnolia Delivery API
这种方式适合需要动态加载内容的场景,编辑在AdminCentral里配置组件时,只需指定要展示的内容类型标识,组件在渲染时自行请求数据。
- 第一步:在Magnolia中给组件添加对话框字段,让编辑选择/输入目标内容类型的名称(比如
contentType字段)。 - 第二步:在Next.js组件中,通过
useEffect或数据请求库调用Magnolia Delivery API获取对应内容:
import { useEffect, useState } from 'react'; export default function ContentListComponent(props) { const [contentItems, setContentItems] = useState([]); const { contentType } = props; // 编辑器配置的内容类型字段 useEffect(() => { if (!contentType) return; // 替换为你的Magnolia实例Delivery API地址 fetch(`https://your-magnolia-instance.com/.rest/delivery/v1/${contentType}`) .then(res => res.json()) .then(data => setContentItems(data.results)) .catch(err => console.error('获取内容失败:', err)); }, [contentType]); return ( <div className="content-list"> {contentItems.map(item => ( <div key={item['@id']} className="content-item"> <h3>{item.title}</h3> <p>{item.description}</p> </div> ))} </div> ); }
- 注意事项:
- 配置Next.js代理避免CORS问题,或确保Delivery API对外可访问。
- 用SWR/React Query做缓存和重新验证,提升性能。
- 确保AdminCentral预览环境下API请求能正常到达Magnolia实例。
方案2:扩展页面getStaticProps预取内容(SSG友好)
如果希望内容在静态生成阶段就完成预渲染,可在pages/[[pathname]].js的getStaticProps中提前解析页面组件配置,预取对应内容类型的数据后传递给组件。
- 第一步:同样在组件对话框中添加
contentType配置字段。 - 第二步:在页面的
getStaticProps中遍历组件树,批量预取内容:
export async function getStaticProps(context) { // 原有获取页面内容的逻辑 const pageContent = await fetchMagnoliaPageContent(context.params.pathname); const contentRequests = []; const targetComponents = []; // 递归遍历组件,收集需要预取内容的组件 function traverseComponents(components) { components.forEach((component, index) => { if (component['@nodeType'] === 'your-content-list-component-type' && component.contentType) { targetComponents.push({ index, contentType: component.contentType }); contentRequests.push( fetch(`https://your-magnolia-instance.com/.rest/delivery/v1/${component.contentType}`) .then(res => res.json()) ); } // 处理嵌套组件 if (component.components) traverseComponents(component.components); }); } if (pageContent.components) traverseComponents(pageContent.components); // 批量请求内容数据 const contentResults = await Promise.all(contentRequests); // 将数据注入对应组件的props targetComponents.forEach(({ index }, resultIndex) => { pageContent.components[index].contentData = contentResults[resultIndex].results; }); return { props: { pageContent }, revalidate: 60, // 可选:开启增量静态再生,定期更新内容 }; }
- 第三步:组件直接使用预取的
contentData:
export default function ContentListComponent(props) { const { contentData } = props; return ( <div className="content-list"> {contentData.map(item => ( <div key={item['@id']} className="content-item"> <h3>{item.title}</h3> <p>{item.description}</p> </div> ))} </div> ); }
- 注意事项:
- 需准确匹配组件的
@nodeType,避免误处理其他组件。 - 递归遍历要覆盖组件嵌套的场景(如容器组件内的子组件)。
- 需准确匹配组件的
方案3:利用Magnolia Next.js集成工具的内置方法
Magnolia官方的@magnolia/nextjs-connector包提供了简化的内容获取方式,可直接在组件中调用内置方法获取内容类型数据。
- 第一步:确保已安装并配置
@magnolia/nextjs-connector。 - 第二步:在组件中使用上下文获取客户端并请求内容:
import { useMagnoliaContext } from '@magnolia/nextjs-connector'; import { useEffect, useState } from 'react'; export default function ContentListComponent(props) { const { contentType } = props; const { client } = useMagnoliaContext(); const [contentItems, setContentItems] = useState([]); useEffect(() => { if (!client || !contentType) return; async function fetchContent() { try { const response = await client.getNodes(contentType); setContentItems(response.results); } catch (err) { console.error('获取内容失败:', err); } } fetchContent(); }, [client, contentType]); return ( <div className="content-list"> {contentItems.map(item => ( <div key={item['@id']} className="content-item"> <h3>{item.title}</h3> <p>{item.description}</p> </div> ))} </div> ); }
- 注意事项:
- 需在
_app.js中正确配置MagnoliaContext,确保客户端实例正常初始化。 - 该方式会自动处理API路径和认证配置,减少手动编码工作量。
- 需在
内容的提问来源于stack exchange,提问作者Subin Paul
相关产品推荐
相关产品推荐

