如何让Gatsby处理Directus嵌套GraphQL字段中的外部图片资源?
解决Gatsby处理Directus深层嵌套外部图片链接的方案
核心思路
通过在gatsby-node.js中手动抓取image_ext字段的外部链接,将图片下载到本地并创建Gatsby可识别的File节点,再关联到原Directus文章节点上,最终用Gatsby的图片插件进行优化渲染。
步骤1:安装必要依赖
需要用到文件下载、图片处理相关的插件:
npm install gatsby-source-filesystem gatsby-plugin-sharp gatsby-transformer-sharp gatsby-plugin-image axios dotenv
步骤2:配置环境变量
在项目根目录创建.env文件,填入Directus的访问信息(用于访问私有资源):
DIRECTUS_URL=https://你的directus地址 DIRECTUS_API_TOKEN=你的directus访问令牌
步骤3:修改gatsby-config.js
启用Directus数据源和图片处理插件:
require('dotenv').config(); module.exports = { plugins: [ 'gatsby-plugin-image', 'gatsby-plugin-sharp', 'gatsby-transformer-sharp', { resolve: 'gatsby-source-directus', options: { url: process.env.DIRECTUS_URL, token: process.env.DIRECTUS_API_TOKEN, }, }, ], };
步骤4:编写gatsby-node.js处理图片下载
在这个文件中,我们遍历Directus的文章节点,下载image_ext对应的图片并关联到节点:
const { createRemoteFileNode } = require('gatsby-source-filesystem'); exports.onCreateNode = async ({ node, actions, createNodeId, getCache }) => { const { createNode, createParentChildLink } = actions; // 仅处理Directus文章节点 if (node.internal.type === 'DirectusArticles') { const imageUrl = node.image_ext; if (!imageUrl) return; try { // 创建远程文件节点,携带认证头访问私有资源 const fileNode = await createRemoteFileNode({ url: imageUrl, parentNodeId: node.id, createNode, createNodeId, getCache, httpHeaders: { Authorization: `Bearer ${process.env.DIRECTUS_API_TOKEN}`, }, }); if (fileNode) { // 将图片节点与文章节点关联 createParentChildLink({ parent: node, child: fileNode }); node.localImage___NODE = fileNode.id; } } catch (err) { console.error(`图片下载失败 ${imageUrl}:`, err); } } };
步骤5:修改GraphQL查询获取处理后的图片
现在可以查询到本地处理后的图片节点,用于优化渲染:
query Articles { directus { articles { image_ext localImage { childImageSharp { gatsbyImageData(width: 800, quality: 80) } } } } }
步骤6:组件中渲染优化后的图片
使用GatsbyImage组件渲染处理后的图片:
import { GatsbyImage, getImage } from 'gatsby-plugin-image'; export default function ArticleList({ data }) { return ( <div className="article-list"> {data.directus.articles.map((article) => { const image = getImage(article.localImage); return ( <div key={article.id} className="article-item"> {image && <GatsbyImage image={image} alt="文章配图" />} </div> ); })} </div> ); }
内容的提问来源于stack exchange,提问作者Sergey
相关产品推荐
相关产品推荐

