1

I have a NextJS project with a bare-bones <PostList /> component where I retrieve some test data from a GraphQL server using the react-apollo module:

import { gql, graphql } from "react-apollo";
import withData from "../../apollo/withData";

const GET_POSTS = gql`
  {
    posts {
      _id
      title
    }
  }
`;

const PostList = ({ data: { loading, posts } }) => {
  if (loading) {
    return <div>Loading...</div>;
  } else {
    return (
      <ul>
        {posts.map(post => <li key={post._id}>{post.title}</li>)}
      </ul>
    );
  }
};

export default withData(graphql(GET_POSTS)(PostList));

This works perfect. But now I'd like to take that query definition out and give it a separate .graphql (or .gql) file of its own. Something like this:

// apollo/get-posts-query.graphql
{
  posts {
    _id
    title
  }
}

My question is, how do I import this file into my component without having to turn it into a javascript code? I mean, I don't want to use any non-graphql code in my .graphql file (so no module.exports export default, etc.).

Here's all that I've tried:

Using webpack:

/* eslint-disable no-unused-vars */

import withCSS from '@zeit/next-css';
import withSass from '@zeit/next-sass';
import dotenv from 'dotenv';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import glob from 'glob';
import withPurgeCss from 'next-purgecss';
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import path from 'path';
import webpack from 'webpack';
import 'graphql-tag/loader';

const { parsed: localEnv } = dotenv.config();

module.exports = withCSS(withSass(withPurgeCss({
  distDir: '.build',
  purgeCssPaths: [
    'pages/**/*',
    'components/**/*',
  ],
  webpack: (config, { dev, isServer }) => {
    if (isServer) {
      return config;
    }
    config.module.rules.push({
      test: /\.(graphql|gql)$/,
      exclude: /node_modules/,
      loader: 'graphql-tag/loader',
    });
    config.plugins.push(
      new webpack.DefinePlugin({
        'process.env': {
          BASE_URL: JSON.stringify(process.env.BASE_URL),
        },
      }),
      new webpack.EnvironmentPlugin(localEnv),
      new webpack.optimize.LimitChunkCountPlugin({
        maxChunks: 1,
      }),
    );
    config.optimization.minimizer.push(
      new OptimizeCSSAssetsPlugin({}),
    );
    return config;
  },
  env: {
    REDIS_PORT: process.env.REDIS_PORT,
    REDIS_HOST: process.env.REDIS_HOST,
  },
})));

This setup throws the following error (refuses to even recognize the loader!):

> ./apollo/test.graphql 2:8
Module parse failed: Unexpected token (2:8)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| {
>   posts {
|     _id
|     title

Using Babel:

I added the babel-plugin-import-graphql babel plugin (yarn add -D babel-plugin-import-graphql to my dev dependencies). Then updated my .babelrc as follows:

{
  "presets": [
    "next/babel"
  ],
  "plugins": [["styled-components", { "ssr": true }], "import-graphql"]
}

This throws the following error:

> Build error occurred { Invariant Violation: Argument of {   posts {
>     _id
>     title
>     secondaryTitle   } }  passed to parser was not a valid GraphQL DocumentNode. You may need to use 'graphql-tag' or another method to
> convert your operation into a document
>     at invariant (/home/ubuntu/proost/web-no-apollo/node_modules/invariant/invariant.js:40:15)

Any third alternative?

Alex
  • 171
  • 2
  • 10
TheLearner
  • 2,813
  • 5
  • 46
  • 94
  • webpack: looks like the loader doesn't get run, try console.logging the export to see what the loader rules are. The babel error is because the loader doesn't run – w00t Sep 20 '19 at 11:22

1 Answers1

2

You need a bundler like Webpack that lets you define how to load .graphql files. Then you just import the graphql file and use the resulting query string/object as before.

One possibility is webpack-graphql-loader, but Apollo recommends using graphql-tag.

In any case, you could try this approach specifically for Next.js.

w00t
  • 17,944
  • 8
  • 54
  • 62