Nous introduisons des articles depuis un backend Wordpress, certains ont des images (dans un champ ACF) et d'autres pas. Le problème est que Gatsby infère le schéma basé sur le premier nœud s'il reçoit un nœud sans image, le schéma est incorrect.
D'où vient le schéma GraphQL de Gatsby? Avec Gatsby, nous utilisons des plugins qui récupèrent les données de différentes sources. Nous utilisons ensuite ces données pour déduire automatiquement un schéma GraphQL.
Comment pouvons-nous dicter un schéma à GraphQL/Gatsby qui inclut toujours une image, avec 'null' comme valeur par défaut si elle est vide?
{
allWordpressWpTestimonial {
edges {
node {
id
title
acf {
photo_fields {
photo {
id
localFile {
childImageSharp {
sizes {
src
}
}
}
}
}
}
}
}
}
}
Dans l'exemple ci-dessus, parfois 'photo' n'existe pas et ça casse tout ...
Configuration Gatsby:
const innertext = require('innertext')
const url = require('url')
module.exports = {
siteMetadata: {
title: 'Test',
googleMapsAPIKey: 'xxxxxx',
adminBaseUrl: '123.123.123',
adminProtocol: 'http',
},
pathPrefix: '/web/beta',
plugins: [
'gatsby-plugin-react-next',
'gatsby-plugin-react-helmet',
'gatsby-plugin-sharp',
'gatsby-plugin-svgr',
{
resolve: 'gatsby-plugin-google-analytics',
options: {
trackingId: 'GOOGLE_ANALYTICS_TRACKING_ID',
},
},
{
resolve: 'gatsby-plugin-bugherd',
options: {
key: 'xxxxxx',
showInProduction: true,
},
},
{
resolve: '@andrew-codes/gatsby-plugin-elasticlunr-search',
options: {
fields: ['title', 'url', 'textContent', 'urlSearchable'],
resolvers: {
wordpress__PAGE: {
title: node => node.title,
textContent: node => innertext(node.content),
url: node => url.parse(node.link).path,
urlSearchable: node =>
url
.parse(node.link)
.path.split('/')
.join(' '),
},
wordpress__POST: {
title: node => node.title,
textContent: node => innertext(node.content),
url: node => `/news/${node.slug}`,
urlSearchable: node =>
url
.parse(node.link)
.path.split('/')
.join(' '),
},
wordpress__wp_industry: {
title: node => node.title,
textContent: node => innertext(node.content),
url: node => `/business/industries/${node.slug}`,
urlSearchable: node =>
url
.parse(node.link)
.path.split('/')
.join(' '),
},
},
},
},
{
resolve: 'gatsby-source-wordpress',
options: {
baseUrl: 'xxxxxx',
protocol: 'http',
hostingWPCOM: false,
useACF: true,
auth: {
htaccess_user: 'admin',
htaccess_pass: 'xxxxxx',
htaccess_sendImmediately: false,
},
verboseOutput: false,
},
},
'gatsby-transformer-sharp',
],
}
Cela fait un moment depuis ce post, mais depuis la version 2.2 Gatsby a ajouté une nouvelle API qui facilitera la personnalisation du schéma. Ce n'est pas un exemple avec wordpress mais avec gatsby's gatsby-transformer-remark
, mais je suis sûr que c'est applicable.
J'ai un tas de .md
avec frontmatter ressemble à ceci:
---
title: "Screen title"
image: "./hero-image.png" <--- sometimes it's an empty string, ""
category: "Cat"
---
...content...
Si Gatsby arrive au .md
avec l'image vide en premier, il déduira incorrectement ce champ comme String
, même s'il doit être File
. Avec la nouvelle API, je peux informer Gatsby du champ d'image dans gatsby-node.js
:
exports.sourceNodes = ({ actions, schema }) => {
const { createTypes } = actions
createTypes(`
type MarkdownRemarkFrontmatter {
image: File
}
type MarkdownRemark implements Node {
frontmatter: MarkdownRemarkFrontmatter
}
`)
}
Cela garantira que le champ image
sera toujours de type File, sinon ce sera null
.
Quelques notes:
MarkdownRemark
doivent implémenter Node
MarkdownRemarkFrontmatter
, puis le transmettre au champ frontmatter
dans le nœud MarkdownRemark
.category
dans MarkdownRemarkFrontmatter
, il sera déduit par Gatsby comme avant.MarkdownRemark
, MarkdownRemarkFrontmatter
) est de les rechercher dans graphiql (par défaut à localhost:8000/___graphql
)Commencez-vous par utiliser les plug-ins Gatsby-plugin-sharp, Gatsby-transform-sharp & Gatsby-source-WordPress?
Mon site utilise le plugin Gatsby-source-Wordpress ainsi que la bibliothèque pointue ainsi que Bluebird pour renvoyer des promesses, etc. Définissez l'ImageURL sur votre Post.js ou Page.js. L'URL source est produite lorsqu'elle est chargée dans ma bibliothèque multimédia mais est déchargée dans un compartiment S3 car mon site WordPress est construit "par programme". L'URL source est généralement définie par vous et peut être choisie dans Types de champs ACF lors de la création d'un modèle de publication de page.
export const pageQuery = graphql`
query homePageQuery {
site {
siteMetadata {
title
subtitle
description
}
}
allWordpressPost(sort: { fields: [date] }) {
edges {
node {
title
excerpt
slug
type
_image{
source_url
}
categories {
slug
name
}
}
}
}
}
L'interrogation des données dans l'ordre exact est un must pour chaque type de publication ou GraphQL ne renverra pas le schéma correctement, ce qui produira une erreur. Aussi simple que cela puisse paraître et faisant double emploi, il devra y avoir deux schémas GraphQL différents à la fois et deux fichiers post1.js exemple post1.js et post2.js définissant les différentes catégories de messages. 1. Recherchez le retour avec l'URL des images. 2. Requête pour le retour sans images. égal à nul ou inexistant C'est une chute de GraphQL qu'il s'attend à recevoir X et quand Y arrive, il devient mécontent et échoue.
Vous pouvez également essayer ceci lorsque vous recevez l'image, la transformer avec sharp en href = et la transformer de https pour la dimensionner à la réception, mais dans votre schéma de cas, elle sera nulle. Nous l'avons fait pour une page bio d'un employé qui revenait d'un ancien site WordPress.
/**
* Transform internal absolute link to relative.
*
* @param {string} string The HTML to run link replacemnt on
*/
linkReplace(string) {
// console.log(string)
const formatted = string.replace(
/(href="https?:\/\/dev-your-image-api\.pantheonsite\.io\/)/g,
`href="/`
)
return formatted
}
render() {
const post = { ...this.props.data.wordpressPost }
const headshot = { ...this.props.data.file.childImageSharp.resolutions }
const { percentScrolled } = { ...this.state }
const contentFormatted = this.linkReplace(post.content)
return (
<div ref={el => (this.post = el)}>
<div className={styles.progressBarWrapper}>
<div
style={{ width: `${percentScrolled}%` }}
className={styles.progressBar}
/>
</div>
<div className={styles.post}>
<h1
className={styles.title}
dangerouslySetInnerHTML={{ __html: post.title }}
/>
<div
className={styles.content}
dangerouslySetInnerHTML={{ __html: contentFormatted }}
/>
<Bio headshot={headshot} horizontal={true} />
</div>
</div>
)
}
}
Post.propTypes = {
data: PropTypes.object.isRequired,
}
export default Post
export const postQuery = graphql`
query currentPostQuery($id: String!) {
wordpressPost(id: { eq: $id }) {
wordpress_id
title
content
slug
}
file(relativePath: { eq: "your-image-headshot.jpg" }) {
childImageSharp {
resolutions(width: 300, height: 300) {
...GatsbyImageSharpResolutions
}
}
}
}
"
J'espère que cela vous aide à me contacter.
Il y a un plugin pour ça, et c'est génial. Je l'utilise spécifiquement avec le plugin source Wordpress.
Notez que vous devrez peut-être également ajouter un graphql.config.json
fichier dans votre répertoire racine pour votre IDE pour le récupérer correctement:
{
"schema": {
"file": "schema.json"
}
}