我遵循了Gatsby教程,该教程在Markdown文章和Pages中使用图像,效果很好,但是我想要实现的是从静态位置获取图像,而不是使用图像的相对路径。
想参考这样的图像(在前)
featuredImage: img/IMG_20190621_112048_2.jpg
凡IMG_20190621_112048_2.jpg是/src/data/img
不是同一个目录下的文件降价/src/posts
我试图这样设置gatsby-source-filesystem
:
{
resolve: `gatsby-source-filesystem`,
options: {
name: `posts`,
path: `${__dirname}/src/posts`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `data`,
path: `${__dirname}/src/data/`,
},
},
但是帖子模板中的graphQL查询失败:
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
featuredImage {
childImageSharp {
fluid(maxWidth: 800) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
GraphQL错误字段“ featuredImage”必须没有选择,因为类型“ String”没有子字段。
知道如何从不同于post markdown目录的位置获取图像吗?
在Gatsby中实现此功能以前是很麻烦的,但是由于有了新的createSchemaCustomization
Node API文档(自Gatsby 2.5起),它相对容易。
这是一个演示,您可以在其中复制您的回购结构:github
这是相关代码所在的位置:github
这是使其工作的代码:
// gatsby-node.js
const path = require('path')
exports.createSchemaCustomization = ({ actions }) => {
const { createFieldExtension, createTypes } = actions
createFieldExtension({
name: 'fileByDataPath',
extend: () => ({
resolve: function (src, args, context, info) {
const partialPath = src.featureImage
if (!partialPath) {
return null
}
const filePath = path.join(__dirname, 'src/data', partialPath)
const fileNode = context.nodeModel.runQuery({
firstOnly: true,
type: 'File',
query: {
filter: {
absolutePath: {
eq: filePath
}
}
}
})
if (!fileNode) {
return null
}
return fileNode
}
})
})
const typeDefs = `
type Frontmatter @infer {
featureImage: File @fileByDataPath
}
type MarkdownRemark implements Node @infer {
frontmatter: Frontmatter
}
`
createTypes(typeDefs)
}
分为两个部分:
markdownRemark.frontmatter.featureImage
以便graphql通过以下方式解析为File节点而不是字符串createTypes
@fileByDataPath
通过createFieldExtension
现在,盖茨比将其推断frontmatter.featureImage
为字符串。我们将要求Gatsby通过修改其父类型来将featureImage读取为字符串:
type Frontmatter {
featureImage: File
}
但是,这还不够,我们还需要将此Frontmatter
类型传递给其父级:
type Frontmatter {
featureImage: File
}
type MarkdownRemark implements Node {
frontmatter: Frontmatter
}
我们还将添加@infer
标记,让Gatsby知道它可以推断出这些类型的其他字段frontmatter.title
,例如markdownRemark.html
,等。
然后将这些自定义类型传递给createTypes
:
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
const typeDefs = `
type Frontmatter @infer {
featureImage: File
}
type MarkdownRemark implements Node @infer {
frontmatter: Frontmatter
}
`
createTypes(typeDefs)
}
现在,我们可以启动localhost:8000/___graphql
并尝试查询图像
query Post {
markdownRemark {
frontmatter {
featureImage {
id
}
}
}
}
我们得到...
错误:无法为非空字段File.id返回null。
这是因为尽管盖茨比现在知道featureImage
应该是“文件”节点,但是却不知道从何处获取该文件。
此时,我们可以使用createResolvers
手动将字段解析为“文件”节点,或者createFileExtension
执行相同的操作。我createFileExtension
之所以选择它,是因为它允许更多的代码重用(您可以扩展任何字段),而createResolvers
在这种情况下,它对特定字段更有用。看到您只想从src/data
目录中解析文件,我将其称为扩展名fieldByDataPath
。
让我们看一下resolve属性。该函数具有以下功能:
frontmatter
)featureImage
在查询中传递给的参数。我们不需要这个nodeModel
,我们将使用它从Gatsby节点存储中获取节点我们将从中找到原始路径(img/photo.jpg
)src.featureImage
,然后将其粘贴src/data
以获取完整的绝对路径。接下来,我们查询nodeModel以查找具有匹配的绝对路径的File节点。既然你已经指出gatsby-source-filesystem
来src/data
,图像(photo.jpg)将在盖茨比节点商店。
如果我们找不到路径或匹配的节点,请返回null
。
resolve: async function (src, args, context) {
// look up original string, i.e img/photo.jpg
const partialPath = src.featureImage
if (!partialPath) {
return null
}
// get the absolute path of the image file in the filesystem
const filePath = path.join(__dirname, 'src/data', partialPath)
// look for a node with matching path
const fileNode = await context.nodeModel.runQuery({
firstOnly: true,
type: 'File',
query: {
filter: {
absolutePath: {
eq: filePath
}
}
}
})
// no node? return
if (!fileNode) {
return null
}
// else return the node
return fileNode
}
我们已经完成了99%的工作。最后要做的是将其传递给此解析函数createFieldExtension
;并将新扩展名添加到createTypes
createFieldExtension({
name: 'fileByDataPath' // we'll use it in createTypes as `@fileByDataPath`
extend: () => ({
resolve, // the resolve function above
})
})
const typeDef = `
type Frontmatter @infer {
featureImage: File @fileByDataPath // <---
}
...
`
这样,您现在就可以使用src/data/
frontmatter中的相对路径了。
fileByDataPath
实施方式仅适用于名为的字段featureImage
。这不是太有用,所以我们应该对其进行修改,以使其可以在名称以_data
;结尾的任何字段上使用。或至少接受要处理的字段名称列表。
Edit的时间很有限,所以我编写了一个插件来完成此任务,并为此写了博客。
此后,“编辑2盖茨比”已实现runQuery
异步(2020年7月),更新了答案以反映这一点。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句