Patrik Rikama-Hinnenberg
Patrik Rikama-Hinnenberg

Reputation: 1600

Only one page generated to sitemap with gatsby-plugin-sitemap

I am not able to create a sitemap for my Gatsy site.

The default setting of the plugin creates only one page even there is several pages:

<sitemap>
<loc>https://www.thesite.nl/sitemap/sitemap-0.xml</loc>
</sitemap>

If I try to override the default setting with:

query: `{
          site {
            siteMetadata {
              siteUrl
            }
          }
          allSitePage {
            nodes {
              path
            }
          }
        }`,
        serialize: ({ site, allSitePage }) =>
          allSitePage.nodes
            .filter(node => {
              const path = node.path
              console.log({ path })
              // Filter out 404 pages
              if (path.includes("404")) {
                return false
              }
              // Filter out base pages that don't have a language directory
              return supportedLanguages.includes(path.split("/")[1])
            })
            .map(node => {
              return {
                url: `${site.siteMetadata.siteUrl}${node.path}`,
                changefreq: `weekly`,
                priority: 0.7,
              }
            }),

I get TypeError: Cannot read property 'nodes' of undefined Problem is that with gatsby develop I can query the nodes like this and get the paths even it says undefined here.

I have Gatsby v3 and the only plugin I can think might affect could be "gatsby-plugin-intl": "^0.3.3",.

{
      resolve: `gatsby-plugin-intl`,
      options: {
        // language JSON resource path
        path: `${__dirname}/src/intl`,
        // supported language
        languages: [`nl`, `en`],
        language: `nl`,
        // language file path
        defaultLanguage: `nl`,
        // option to redirect to `/nl` when connecting `/`
        redirect: false,
      },
    },

Any ideas?

Got it to build via custom options with gatsby build && gatsby serve after @FerranBuireu suggestion to change the query and now it looks like this but sitemap is still empty:

const siteUrl = process.env.URL || `https://www.thesite.nl`
 {
      resolve: "gatsby-plugin-sitemap",
      options: {
        query: `
        {
          allSitePage {
            nodes {
              path
            }
          }
        }
      `,
        resolveSiteUrl: () => siteUrl,
        resolvePages: ({ allSitePage: { nodes: allPages } }) => {
          return allPages.map(page => {
            return { ...page }
          })
        },
        serialize: ({ path }) => {
          return {
            url: path,
          }
        },
      },
    },

Upvotes: 3

Views: 1552

Answers (2)

Patrik Rikama-Hinnenberg
Patrik Rikama-Hinnenberg

Reputation: 1600

After mental and technical support from Ferran Buireu I managed to dig deeper.

In the public folder the sitemap was found under sitemap/sitemap-0.xml giving the right path to all pages at thesite.nl/sitemap/sitemap-0.xml

Also notable that the <sitemapindex> is a valid element that points to the sitemap-0: https://www.sitemaps.org/protocol.html. Google search console still wants the /sitemap/sitemap-0.xml if submitted there.

So looks like the output of the pages was there most of the time. #idiot

Upvotes: 0

Ferran Buireu
Ferran Buireu

Reputation: 29315

I think your issue comes because you are not setting the resolveSiteUrl and, in this scenario, the siteUrl needs to be present. According to the docs:

siteMetadata: {
  // If you didn't use the resolveSiteUrl option this needs to be set
  siteUrl: `https://www.example.com`,
},

An ideal full configuration should be:

const siteUrl = process.env.URL || `https://fallback.net`

// In your gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: "gatsby-plugin-sitemap",
      options: {
        query: `
        {
          allSitePage {
            nodes {
              path
            }
          }
          allWpContentNode(filter: {nodeType: {in: ["Post", "Page"]}}) {
            nodes {
              ... on WpPost {
                uri
                modifiedGmt
              }
              ... on WpPage {
                uri
                modifiedGmt
              }
            }
          }
        }
      `,
        resolveSiteUrl: () => siteUrl,
        resolvePages: ({
          allSitePage: { nodes: allPages },
          allWpContentNode: { nodes: allWpNodes },
        }) => {
          const wpNodeMap = allWpNodes.reduce((acc, node) => {
            const { uri } = node
            acc[uri] = node

            return acc
          }, {})

          return allPages.map(page => {
            return { ...page, ...wpNodeMap[page.path] }
          })
        },
        serialize: ({ path, modifiedGmt }) => {
          return {
            url: path,
            lastmod: modifiedGmt,
          }
        },
      },
    },
  ],
}

Tweak it and adapt it to fit your query.

I would do something like:

    resolveSiteUrl: () => siteUrl,
    resolvePages: ({
      allSitePage: { nodes: allPages },
    }) => {
      const sitePageNodeMap = allSitePage.reduce((acc, node) => {
        const { uri } = node
        acc[uri] = node

        return acc
      }, {})

      return allPages.map(page => {
        return { ...page, ...sitePageNodeMap[page.path] }
      })
    },
    serialize: ({ path, modifiedGmt }) => {
      return {
        url: path,
        lastmod: modifiedGmt,
      }
    },

Upvotes: 2

Related Questions