Create-react-app: Proposal: importing .graphql files should be enabled

Created on 11 Mar 2017  Â·  20Comments  Â·  Source: facebook/create-react-app

Right now I need to eject in order to import .graphql files (using graphql-tag/loader) . I would think graphQl is some kind of core technology that should be supported out of the box ?

proposal

Most helpful comment

Importing .graphql files will work out of the box with no extra manipulation in 2.x: https://github.com/facebook/create-react-app/pull/3909

All 20 comments

Ejected for this same reason.

I’m open to supporting this, but is it Apollo-specific? Would it work for people using Relay Modern too?

I dont _think_ it's apollo specific -- but I have not verified yet.

From this:

query ChannelsList {
  channels {
    id
    name
  }
}

You end up with this:

{
  "kind": "Document",
  "definitions": [
    {
      "kind": "OperationDefinition",
      "operation": "query",
      "name": {
        "kind": "Name",
        "value": "ChannelsList"
      },
      "variableDefinitions": [],
      "directives": [],
      "selectionSet": {
        "kind": "SelectionSet",
        "selections": [
          {
            "kind": "Field",
            "alias": null,
            "name": {
              "kind": "Name",
              "value": "channels"
            },
            "arguments": [],
            "directives": [],
            "selectionSet": {
              "kind": "SelectionSet",
              "selections": [
                {
                  "kind": "Field",
                  "alias": null,
                  "name": {
                    "kind": "Name",
                    "value": "id"
                  },
                  "arguments": [],
                  "directives": [],
                  "selectionSet": null
                },
                {
                  "kind": "Field",
                  "alias": null,
                  "name": {
                    "kind": "Name",
                    "value": "name"
                  },
                  "arguments": [],
                  "directives": [],
                  "selectionSet": null
                }
              ]
            }
          }
        ]
      }
    }
  ],
  "loc": {
    "start": 0,
    "end": 55,
    "source": {
      "body": "query ChannelsList {\n  channels {\n    id\n    name\n  }\n}",
      "name": "GraphQL"
    }
  }
}

Looks like Relay.QL is vastly different. It uses a precompiled schema and validates your graphql against it. Whereas graphql-tag/loader just spits out the document and handles imports (that also might be a graphql-tag/loader specific concept).

Yep, I'm having to eject too on a brand new project just to support this.

Really good if there were a way to bake this in, or even better add custom loaders somehow 🙌

As of Relay Modern, there must be "babel-plugin-relay" baked into the Babel config.

Has anyone had any further thoughts on how we best implement this?

Graphcool today announced graphql-cli and it would be awesome to submit a PR over there that CRA works out of the box with graphql-cli.

Note this issue won't progress by itself. If you're interested in this please create a proof of concept, send a PR, help us understand whether it's Apollo-specific or not, etc. Thanks!

@gaearon - From what I have tested so far, it is Apollo-specific. Would a good alternative be to add both graphql-tag/loader and babel-plugin-relay to CRA to handle both use-cases?

If the above isn't a good alternative, I only see two other options:

  1. Don't support it. Let users continue to eject from CRA to add this manually.

  2. Someone (possibly myself) can write a Webpack Plugin to handle both Relay and Apollo. I have no idea what the implementation would look like or even if the two would play nicely together. I wish I had a better answer but I'd have to play around with it before giving anything concrete. Sorry 😞

(Or just support one. I don't see that as an ideal solution, though.)

For Relay, I’d like to see if recently merged babel-plugin-macros support is enough.

For Apollo, it seems to me odd to hardcode a filetype loader to a specific library 😞 But maybe if apollo is in package.json we could do it automatically. The trick is how to make sure every ejected user doesn’t have to deal with config for this if they don’t use this.

I haven't seen babel-plugin-macros yet so I'll have to research it/dig through the source.

Ideally, we should have a global GraphQL plugin/loader that handles Apollo, Relay, and any other GraphQL lib/framework.

I'm not sure about a good solution to the last statement you made. For users who are not using GraphQL, it adds a bit more bloat to the node_modules but past that, it shouldn't affect the rest of the app. I'm not sure though

I'll note that if we come up with a good solution, I'm more than happy to submit a PR to close this issue.

Someone could probably build a macro to support reading in .graphql files:

// some-file.js
import graphqlLoader from './graphql-loader.macro'

const query = graphqlLoader('./query.graphql')




// graphql-loader.macro.js
const {createMacro} = require('babel-plugin-macros')

module.exports = createMacro(graphqlLoaderMacro)

function graphqlLoaderMacro({references, state, babel}) {
  const {file: {opts: {filename}}} = state
  references.default.forEach(graphqlLoader => {
    const relativeQueryPath = graphqlLoader.parentPath.get('arguments')[0].node.value
    const queryPath = path.relative(filename, relativeQueryPath)
    // do the queryPath loading thing
    // replace graphqlLoader.parentPath with whatever you loaded...
  })
}

The cool thing is you could do this locally in your own project before it's even published to npm. All without having to configure anything at all. Then when someone's got a good working version they can publish it to npm and anyone can use it. It's 100% explicit what's going on and it works without any configuration necessary! :tada:

Smart. Since we landed babel-plugin-macros support let's just close this, and then somebody can build a macro for it.

@kentcdodds I'd like to see the setup for this and how to use in practice as an example if possible.

@ibigpapa,

I don't know if I have time. I also don't know much about graphql, so I may not be the right one to make this. But it does seem interesting to me, so if I have time I'll work on it.

Honestly I don't think it's much more than my example above. You'll probably need fs.readFileSync to read the file to a string, then do whatever processing you need to convert it to the format needed, then convert that to an object AST and call graphqlLoader.parentPath.replaceWith(yourQueryObjectAST). I wouldn't say it's "easy," but it shouldn't be too much more than what I provided above.

For folks wanting to learn more about this, see the babel-plugin-macros author docs which has links to resources about working with ASTs in babel.

@kentcdodds Thank for your suggestion. I try to implement it with babel-plugin-macros. It ls really
cool. 😀 Now, we can import .graphql files without webpack configuration:

$ yarn add graphql.macro
import { loader } from 'graphql.macro';
const query = loader('./fixtures/query.graphql');

      ↓ ↓ ↓ ↓ ↓ ↓

const query = {
  "kind": "Document",
  "definitions": [{
    ...
References

GitHub: https://github.com/evenchange4/graphql.macro
Example: https://github.com/evenchange4/graphql.macro-example
Demo: https://graphqlmacro.netlify.com/

This is super @evenchange4! Would you like to add your macro to the list? And make sure to add the keyword babel-plugin-macros to your package.json so it's easier to find on npm!

Well done @evenchange4! :clap:

Importing .graphql files will work out of the box with no extra manipulation in 2.x: https://github.com/facebook/create-react-app/pull/3909

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ap13p picture ap13p  Â·  3Comments

fson picture fson  Â·  3Comments

jnachtigall picture jnachtigall  Â·  3Comments

DaveLindberg picture DaveLindberg  Â·  3Comments

AlexeyRyashencev picture AlexeyRyashencev  Â·  3Comments