我正在使用Gatsby v5开发我的网站,我目前正在努力解决GraphQL问题。
问题
我使用静态GraphQL查询从一些GitHub存储库中提取 openGraphImageUrl,并在一个card组件中显示每个图像。为了对图像进行更多控制,我编写了一个解析器,它下载 openGraphImageUrl 后面的文件,并将它们作为 File 节点添加到GraphQL数据层,以便我可以使用它们与<GatsbyImage>
组件。
这种方法通常是有效的,我可以构建网站,静态查询提供来自存储库的信息。解析器正确地添加了image
节点和下载的文件,我可以像预期的那样使用<GatsbyImage>
(请参阅下面的内容)。
我面临的问题是下面的错误消息,它只发生在我对页面进行更改然后在**成功运行gatsby develop
后保存它(例如 index.tsx)**时,但在修改不是页面的单个组件时不会发生(例如 code.tsx -见下文):
调用“building-schema”缺少onError处理程序,错误为“Error:架构必须包含唯一命名的类型,但包含多个名为“File”的类型。
当building schema
步骤再次运行时(通过将更改保存到页面来触发),这就是错误发生后构建过程卡住的地方。
我已经连续搜索了几个小时来解决这个问题,我也咨询了ChatGPT,但无济于事。我目前仍然是Gatsby,React和Typescript的初学者。
错误消息提示“File”类型被重新定义,我只是不明白为什么会发生这种情况,我做错了什么。我如何避免“File”类型在架构中被重新定义?我的设置如下所示。
设置
gatsby-config.ts
这是我设置访问GitHub的GraphQL API的地方:
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
});
import type { GatsbyConfig } from "gatsby";
const config: GatsbyConfig = {
graphqlTypegen: true,
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "GitHub",
fieldName: "github",
url: "https://api.github.com/graphql",
headers: {
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
},
fetchOptions: {},
},
},
//... skipping the rest
],
};
export default config;
gatsby-node.js
解析器的创建如下所示。在GitHub_Repository
节点上,它添加一个File
类型的image
节点,并从存储库的 openGraphImageUrl 下载图像数据。然后将其保存为临时文件,将blob读入缓冲区,然后通过调用createFileNodeFromBuffer()
从缓冲区创建实际节点。
const fs = require("fs");
const path = require("path");
const fetch = require("node-fetch");
const { createFileNodeFromBuffer } = require("gatsby-source-filesystem");
exports.createResolvers = async ({
actions: { createNode },
createNodeId,
cache,
store,
createResolvers,
}) => {
const resolvers = {
GitHub_Repository: {
image: {
type: "File",
resolve: async (source) => {
const imageUrl = source.openGraphImageUrl;
const imageNodeId = createNodeId(imageUrl);
const response = await fetch(imageUrl);
const buffer = await response.buffer();
const dirPath = path.join(process.cwd(), "public", "tmp");
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
const filePath = path.join(
dirPath,
imageNodeId,
);
fs.writeFileSync(filePath, buffer);
const fileNode = await createFileNodeFromBuffer({
buffer,
store,
cache,
createNode,
createNodeId,
name: imageNodeId,
});
return fileNode;
},
},
},
};
createResolvers(resolvers);
};
code.tsx
这就是查询的样子:
function QueryGitHubRepositories(): Repository[] {
const data: Data = useStaticQuery(graphql`
{
github {
viewer {
pinnedItems(first: 6, types: REPOSITORY) {
nodes {
... on GitHub_Repository {
id
name
url
openGraphImageUrl
image {
childImageSharp {
gatsbyImageData(layout: FIXED, width: 336, height: 168)
}
}
}
}
}
}
}
}
`);
return data.github.viewer.pinnedItems.nodes.map((node) => node);
}
TL;DR
为了完整起见,下面是相关代码的其余部分。
code.tsx (续)
我为查询方法定义了以下类型(也在 code.tsx 中):
type Repository = {
name?: string | null;
url?: string | null;
openGraphImageUrl?: string | null;
image?: {
childImageSharp: {
gatsbyImageData?: any | null;
};
} | null;
};
type Data = {
github: {
viewer: {
pinnedItems: {
nodes: Repository[];
};
};
};
};
这里使用查询数据来构建带有存储库卡的代码部分(也在 code.tsx 中):
import * as React from "react";
import { graphql, useStaticQuery } from "gatsby";
import { GatsbyImage } from "gatsby-plugin-image";
//skipping type definitions and query here, since they're already shown above
const RepositoryCard = ({ repository }: { repository: Repository }) => {
const imageItem = repository.image?.childImageSharp.gatsbyImageData ?? "";
const altText = repository.name ?? "repository";
return (
<div>
<a href={repository.url ?? ""} target="_blank">
<div className="flex h-fit flex-col">
<GatsbyImage image={imageItem} alt={altText} />
</div>
</a>
</div>
);
};
const CodeSection = () => {
const repositories: Repository[] = QueryGitHubRepositories();
return (
<div className="w-full">
<div className="flex flex-col">
{repositories.map((repository) => (
<RepositoryCard key={repository.name} repository={repository} />
))}
</div>
</div>
);
};
export default CodeSection;
更新
我也尝试了不同的实现,我看了Paul Scanlon的两篇关于adding data to Gatsby's GraphQL data layer和modifying Gatsby's GraphQL data types using createSchemaCustomization的博客文章。然而,我无法正常工作,可能是因为在他的博客文章中,节点是在没有任何源插件的情况下添加的,而我使用的是gatsby-plugin-graphql
。
欢迎提出替代实现的建议。
1条答案
按热度按时间nhaq1z211#
我找到了一个可行的解决方案。我只需要将
gatsby-source-graphql
替换为gatsby-source-github-api
,因为前者显然不支持增量构建:gatsby-config.ts
gatsby-node.js
code.tsx
类型定义
查询