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?

1
  • 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 Commented Sep 20, 2019 at 11:22

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.