gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.28k stars 10.31k forks source link

warn The GraphQL query in the non-page component "./src/templates/default.js" will not be run. #25293

Closed jakehopking closed 4 years ago

jakehopking commented 4 years ago

Description

When running gatsby build the site cannot create pages using a defined template for: allMdx(filter: {frontmatter: {category: {eq: "page"}}}).

However it works with the same exact code for: allMdx(filter: {frontmatter: {category: {eq: "episode"}}}) type.

When running gatsby develop, both templates are successfully used to build pages.

Steps to reproduce

Run gatsby build on my project https://github.com/jakehopking/uitherapy.fm

Expected result

Successfully build static site using defined templates.

Actual result

Build ignores the template for {category: {eq: "page"}} but does not ignore {category: {eq: "episode"}}.

warn The GraphQL query in the non-page component "./src/templates/default.js" will not be run.
Exported queries are only executed for Page components. It's possible you're
trying to create pages in your gatsby-node.js and that's failing for some
reason.

If the failing component(s) is a regular component and not intended to be a page
component, you generally want to use a <StaticQuery> (https://gatsbyjs.org/docs/static-query)
instead of exporting a page query.

If you're more experienced with GraphQL, you can also export GraphQL
fragments from components and compose the fragments in the Page component
query and pass data down into the child component — https://graphql.org/learn/queries/#fragments

Environment

System:
    OS: macOS 10.15.4
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 14.2.0 - ~/.npm/bin/node
    Yarn: 1.22.4 - ~/.npm/bin/yarn
    npm: 6.14.5 - ~/.npm/bin/npm
  Languages:
    Python: 3.8.2 - /Users/jake/.pyenv/shims/python
  Browsers:
    Chrome: 83.0.4103.106
    Safari: 13.1
  npmPackages:
    gatsby: ^2.22.15 => 2.22.15
    gatsby-background-image: ^1.1.1 => 1.1.1
    gatsby-image: ^2.4.7 => 2.4.7
    gatsby-plugin-emotion: ^4.3.4 => 4.3.4
    gatsby-plugin-google-analytics: ^2.3.4 => 2.3.4
    gatsby-plugin-mdx: ^1.2.15 => 1.2.15
    gatsby-plugin-react-helmet: ^3.3.4 => 3.3.4
    gatsby-plugin-react-svg: ^3.0.0 => 3.0.0
    gatsby-plugin-sass: ^2.3.4 => 2.3.4
    gatsby-plugin-sharp: ^2.6.11 => 2.6.11
    gatsby-plugin-typography: ^2.5.4 => 2.5.4
    gatsby-source-filesystem: ^2.3.11 => 2.3.11
    gatsby-transformer-remark: ^2.8.15 => 2.8.15
    gatsby-transformer-sharp: ^2.5.5 => 2.5.5
  npmGlobalPackages:
    gatsby-cli: 2.12.48

gatsby-node.js

const path = require(`path`);
const {createFilePath} = require(`gatsby-source-filesystem`);

exports.onCreateNode = ({node, getNode, actions}) => {
  const {createNodeField} = actions;

  // General MDX pages
  if (node.internal.type === `Mdx` && node.frontmatter.category === `page`) {
    const slug = createFilePath({node, getNode, basePath: `pages`});
    createNodeField({
      name: `slug`,
      node,
      value: slug,
    });
  }

  // Episode MDX pages
  else if (
    node.internal.type === `Mdx` &&
    node.frontmatter.category === `episode`
  ) {
    const slug = createFilePath({
      node,
      getNode,
      basePath: `content`,
    });
    createNodeField({
      name: `slug`,
      node,
      value: slug,
    });
  }
};

exports.createPages = async ({graphql, actions, reporter}) => {
  // Destructure the createPage function from the actions object
  const {createPage} = actions;

  const pages = await graphql(`
    query {
      allMdx(filter: {frontmatter: {category: {eq: "page"}}}) {
        edges {
          node {
            id
            fields {
              slug
            }
            frontmatter {
              path
            }
          }
        }
      }
    }
  `);
  if (pages.errors) {
    reporter.panicOnBuild(
      '🚨  ERROR: Loading "createPages [default pages]" query'
    );
  }
  pages.data.allMdx.edges.forEach(({node}) => {
    createPage({
      path: node.frontmatter.path || node.fields.slug,
      component: path.resolve(`./src/templates/default.js`),
      context: {
        // Data passed to context is available
        // in page queries as GraphQL variables.
        slug: node.fields.slug,
      },
    });
  });

  const episodes = await graphql(`
    query {
      allMdx(filter: {frontmatter: {category: {eq: "episode"}}}) {
        edges {
          node {
            id
            fields {
              slug
            }
            frontmatter {
              path
            }
          }
        }
      }
    }
  `);

  if (episodes.errors) {
    reporter.panicOnBuild(
      '🚨  ERROR: Loading "createPages [episodes pages]" query'
    );
  }
  // Create episode pages.
  // you'll call `createPage` for each episode
  episodes.data.allMdx.edges.forEach(({node}, index) => {
    createPage({
      // This is the slug you created before
      // (or `node.frontmatter.slug`)
      path: node.frontmatter.path || node.fields.slug,
      // This component will wrap our MDX content
      component: path.resolve(`./src/templates/episodes.js`),
      // You can use the values in this context in
      // our page layout component
      context: {id: node.id},
    });
  });
};

gatsby-config.js

// const path = require(`path`);
/**
 * Configure your Gatsby site with this file.
 *
 * See: https://www.gatsbyjs.org/docs/gatsby-config/
 */

module.exports = {
  siteMetadata: {
    author: `Jake Hopking`,
    description: `removed`,
    keywords: `user interface, podcast, design, development, programming, coding, code, ui, user experience, ux, framework, interviews, expertise`,
    subTitle: `The podcast for designers, developers and independent thinkers`,
    title: `UI Therapy`,
    url: `https://uitherapy.fm`,
    rss: `https://feeds.buzzsprout.com/1180283.rss`,
  },
  plugins: [
    {
      resolve: `gatsby-plugin-google-analytics`,
      options: {
        trackingId: `UA-100706005-3`,
        head: true,
        anonymize: true,
      },
    },
    {
      resolve: `gatsby-plugin-mdx`,
      options: {
        defaultLayouts: {
          default: `${__dirname}/src/layouts/layout-default.js`,
        },
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images/`,
        // path: path.join(__dirname, `src`, `images`),
      },
    },
    {
      resolve: 'gatsby-plugin-react-svg',
      options: {
        rule: {
          include: /\.inline\.svg$/,
        },
      },
    },
    // Add a collection called "episodes" that looks
    // for files in episodes/
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'episodes',
        path: `${__dirname}/src/content/episodes/`,
        // path: path.join(__dirname, `src`, `content`, `episodes`),
      },
    },
    `gatsby-plugin-emotion`,
    `gatsby-plugin-sass`,
    `gatsby-plugin-sharp`,
    `gatsby-plugin-react-helmet`,
    `gatsby-transformer-remark`,
    `gatsby-transformer-sharp`,
  ],
};

templates/episodes.js (success)

import React from 'react';
import {graphql} from 'gatsby';
import {MDXProvider} from '@mdx-js/react';
import {MDXRenderer} from 'gatsby-plugin-mdx';
import {Link} from 'gatsby';
import {Helmet} from 'react-helmet';
import ReactPlayer from 'react-player';
import LayoutDefault from '../layouts/layout-default';
import SectionTitleWings from '../components/sections/SectionTitleWings';
import SectionContent from '../components/sections/SectionContent';
import PostHeading from '../components/PostHeading';
import Code from '../components/Code';
import Newsletter from '../components/Newsletter';
import VerticalRule from '../components/VerticalRule';
import PodcastServices from '../components/PodcastServices';

const shortcodes = {Link}; // Provide common components here

export default function EpisodeTemplate({data: {mdx, site}}) {
  return (
    <LayoutDefault>
      <Helmet>
        <title>{`${mdx.frontmatter.title} | ${site.siteMetadata.title} Podcast Episode ${mdx.frontmatter.episodeNo}`}</title>
        <meta
          property="og:audio"
          content={`${site.siteMetadata.url}${mdx.frontmatter.podcastUrl}`}
        />
        <meta property="og:audio:type" content="audio/mp3" />
        <meta
          property="og:title"
          content={`${mdx.frontmatter.title} - ${site.siteMetadata.title}  Podcast Episode ${mdx.frontmatter.episodeNo}`}
        />
        <meta
          property="og:description"
          content={`${site.siteMetadata.title} | ${site.siteMetadata.subTitle}`}
        />
        <meta property="og:type" content="music.song" />
        <meta
          property="og:url"
          content={`${site.siteMetadata.url}${mdx.frontmatter.path}`}
        />
        {`<!-- Twitter -->`}
        <meta
          name="twitter:title"
          content={`${mdx.frontmatter.title} - ${site.siteMetadata.title}  Podcast Episode ${mdx.frontmatter.episodeNo}`}
        />
        <meta
          name="twitter:description"
          content={`${site.siteMetadata.title} | ${site.siteMetadata.subTitle}`}
        />
      </Helmet>
      <SectionTitleWings tag="h2">{`Episode ${mdx.frontmatter.episodeNo}`}</SectionTitleWings>
      <SectionContent>
        <PostHeading tag="h3" className="mt0">
          Play
        </PostHeading>
        <h4 className="font-weight-light mt0" style={{lineHeight: 1.6}}>
          {mdx.frontmatter.title}
          <em style={{opacity: 0.4}}> &mdash; {mdx.frontmatter.date}</em>
        </h4>
        <ReactPlayer
          controls
          url={mdx.frontmatter.podcastUrl}
          width="100%"
          height="50px"
          wrapper="react-player"
          style={{marginBottom: '20px'}}
        />
      </SectionContent>
      <SectionContent className="post">
        <MDXProvider
          components={{
            ...shortcodes,
            h1: (props) => <h1 {...props} className="" />,
            h2: (props) => <PostHeading {...props} tag="h3" />,
            h3: (props) => <h3 {...props} className="" />,
            h4: (props) => <h4 {...props} className="" />,
            h5: (props) => <h5 {...props} className="" />,
            h6: (props) => <h6 {...props} className="" />,
            pre: ({children: {props}}) => {
              if (props.mdxType === 'code') {
                return (
                  <Code
                    codeString={props.children.trim()}
                    language={
                      props.className &&
                      props.className.replace('language-', '')
                    }
                    {...props}
                  />
                );
              }
            },
          }}
        >
          <MDXRenderer>{mdx.body}</MDXRenderer>
        </MDXProvider>
        <hr />
        <p className="mt3 text-center">
          If you can, please support the show:{' '}
          <a
            href="https://www.patreon.com/uitherapy"
            target="_blank"
            rel="noreferrer"
          >
            https://www.patreon.com/uitherapy
          </a>
        </p>
      </SectionContent>
      <SectionContent>
        <PodcastServices />
      </SectionContent>
      <VerticalRule />
      <Newsletter />
      <VerticalRule />
    </LayoutDefault>
  );
}

export const pageQuery = graphql`
  query EpisodeQuery($id: String) {
    site {
      siteMetadata {
        subTitle
        title
        url
      }
    }
    mdx(id: {eq: $id}) {
      id
      body
      frontmatter {
        date(formatString: "DD MMMM, YYYY")
        episodeNo
        podcastUrl
        path
        tags
        title
      }
      excerpt
    }
  }
`;

templates/default.js (failure)

import React from 'react';
import {graphql} from 'gatsby';
import {MDXProvider} from '@mdx-js/react';
import {MDXRenderer} from 'gatsby-plugin-mdx';
import {Link} from 'gatsby';
import LayoutDefault from '../layouts/layout-default';
import SectionTitleWings from '../components/sections/SectionTitleWings';
import SectionContent from '../components/sections/SectionContent';

const shortcodes = {Link}; // Provide common components here

export default function DefaultTemplate({data: {mdx}, props}) {
  return (
    <LayoutDefault {...props}>
      <SectionTitleWings tag="h2">{`${mdx.frontmatter.title}`}</SectionTitleWings>
      <SectionContent className="page">
        <MDXProvider components={shortcodes}>
          <MDXRenderer>{mdx.body}</MDXRenderer>
        </MDXProvider>
      </SectionContent>
    </LayoutDefault>
  );
}

export const pageQuery = graphql`
  query($slug: String!) {
    mdx(fields: {slug: {eq: $slug}}) {
      body
      frontmatter {
        title
        tags
      }
    }
  }
`;

Any help would be massively appreciated. Thanks in advance :)

pieh commented 4 years ago

Can you try to move your .mdx "page" out src/pages to anywhere else just so it's not under src/pages (and likely adjust slug creation after it)?

I think there is some race condition here, because gatsby-plugin-mdx will automatically create pages from .mdx if it's in src/pages, but then you also create pages yourself for same "paths" (but using different template - the default).

I think this work in develop because we do rerun createPages potentially multiple times, but we don't in builds - so I assume in builds auto-creation by mdx "wins" (or runs last) and in develop createPages "wins", because it's called after auto-creation as well

jakehopking commented 4 years ago

@pieh Thanks for your thoughts on this. I was hoping not to have to move things to a new folder structure, but so be it. I've followed your suggestion and all templates are rendering correctly now.

bobgravity1 commented 2 years ago

it seems to be an obnoxious problem with gatsby that happens to me probably every single project now. its really unacceptable of them to not fix this.