Gatsby: Exporting `query` using a named export doesn't work

Created on 15 Apr 2018  路  6Comments  路  Source: gatsbyjs/gatsby

Description

This code works:

export const query = graphql`
  query LayoutQuery {
    site {
      siteMetadata {
        siteName
      }
    }
  }
`

This code doesn't:

const query = graphql`
  query LayoutQuery {
    site {
      siteMetadata {
        siteName
      }
    }
  }
`

export { query }

Steps to reproduce

Try changing somewhere using export const query = ... to a named export like above. You'll see that an error like this occurs:

screen shot 2018-04-14 at 8 20 27 pm

Expected result

Both styles should work fine.

Actual result

Only the first style works.

Environment

  • Gatsby version (npm list gatsby): 1.9.248
  • gatsby-cli version (gatsby --version): 1.1.49
  • Node.js version: v9.11.1
  • Operating System: macOS High Sierra 10.13.3

I am also using TypeScript in case that is relevant.

File contents (if changed):

gatsby-config.js:

module.exports = {
  siteMetadata: {
    siteName: 'my blog'
  },
  plugins: [
    'gatsby-plugin-typescript',
    'gatsby-plugin-catch-links',
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-styled-components',
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/src/pages`,
        name: 'pages'
      }
    },
    {
      resolve: 'gatsby-transformer-remark',
      options: {
        plugins: []
      }
    }
  ]
}

package.json:

{
  "name": "my-blog",
  "version": "0.1.0",
  "description": "blog",
  "license": "MIT",
  "scripts": {
    "start": "gatsby develop",
    "build": "gatsby build",
    "test": "tsc --pretty",
    "format": "prettier --write \"src/**/*.{ts,tsx}\""
  },
  "dependencies": {
    "@types/node": "latest",
    "@types/react": "latest",
    "@types/react-dom": "latest",
    "@types/react-helmet": "latest",
    "babel-plugin-styled-components": "^1.5.1",
    "gatsby": "latest",
    "gatsby-link": "^1.6.40",
    "gatsby-plugin-catch-links": "^1.0.19",
    "gatsby-plugin-react-helmet": "^2.0.10",
    "gatsby-plugin-styled-components": "^2.0.11",
    "gatsby-plugin-typescript": "latest",
    "gatsby-source-filesystem": "^1.5.29",
    "gatsby-transformer-remark": "^1.7.39",
    "react-helmet": "latest",
    "styled-components": "^3.2.5",
    "styled-reset": "^1.3.2"
  },
  "devDependencies": {
    "prettier": "^1.12.0"
  }
}

gatsby-node.js:

const path = require('path')

exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators
  const blogPostTemplate = path.resolve(`src/templates/post.tsx`)

  return graphql(`
    {
      allMarkdownRemark(
        sort: { order: DESC, fields: [frontmatter___date] }
        limit: 1000
      ) {
        edges {
          node {
            excerpt(pruneLength: 250)
            html
            id
            frontmatter {
              date
              path
              title
            }
          }
        }
      }
    }
  `).then(result => {
    if (result.errors) {
      return Promise.reject(result.errors)
    }

    result.data.allMarkdownRemark.edges.forEach(({ node }) => {
      createPage({
        path: node.frontmatter.path,
        component: blogPostTemplate,
        context: {}
      })
    })
  })
}

tsconfig.json:

{
  "compilerOptions": {
    "outDir": "./dist/",
    "sourceMap": true,
    "strict": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "esnext",
    "jsx": "react",
    "lib": ["dom", "esnext"]
  },
  "include": ["./src/**/*"]
}

Most helpful comment

This tripped me up - as from a language point of view, they are identical. Is this in the docs?

All 6 comments

This is because gatsby does static analisys of .js, .jsx, .tsx files to extract queries for pages/layouts. This static analisys is currently set up to handle only your first export "style" presented in your first code snippet.

You are welcome to send PR to enable more robust checks - here would be starting point for that https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/internal-plugins/query-runner/file-parser.js#L81.

Thanks very much for the explanation. Until this is fixed could this issue remain open though? Or are you saying that it is working as designed and that allowing the other code style is more of just a nice-to-have?

I hesitate to reopen this, because this is not bug - it's more of a "limitation". This is one of those things that are nice to have, but implementing this is not as straight forward as one might think - being able to do the way you described would then naturally made people think they can separate queries to separate files and do stuff like

export { nameOfExportedQuery } from './query-in-separate-file.js'

which would involve a loooot more work to handle (like tracking which page components import given query etc)

Yes, I see what you mean. Thanks for the responses!

This tripped me up - as from a language point of view, they are identical. Is this in the docs?

@pieh if I understand correctly, Gatsby doesn't evaluate the exports or imports, but tries to look for the graphql query in the abstract syntax tree?

I ultimately ended up switching the files around for my templates. I'm now using home.query.tsx as the component for createPage, which re-exports the actual component. This still allows me to break up the file, which is what I was after.

home.query.tsx

import { graphql } from "gatsby"
import { HomePage } from "./home.page"

export const query = graphql`
    query HomePageQuery {
    }
`

export default HomePage

home.page.tsx

import React from "react" 

export const HomePage: React.FC<HomePageProps> = ({ data }) => {
    return <span>Hello universe!</span>
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

benstr picture benstr  路  3Comments

brandonmp picture brandonmp  路  3Comments

magicly picture magicly  路  3Comments

hobochild picture hobochild  路  3Comments

KyleAMathews picture KyleAMathews  路  3Comments