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 }
Try changing somewhere using export const query = ... to a named export like above. You'll see that an error like this occurs:

Both styles should work fine.
Only the first style works.
npm list gatsby): 1.9.248 gatsby --version): 1.1.49I am also using TypeScript in case that is relevant.
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/**/*"]
}
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>
}
Most helpful comment
This tripped me up - as from a language point of view, they are identical. Is this in the docs?