Как абстрагировать запрос GraphQL от компонента? - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть проект NextJS с базовым компонентом <PostList />, где я получаю некоторые тестовые данные с сервера GraphQL с помощью модуля react-apollo:

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));

Это прекрасно работает.Но теперь я хотел бы вынуть это определение запроса и предоставить ему отдельный .graphql (или .gql) собственный файл.Примерно так:

// apollo/get-posts-query.graphql

{
  posts {
    _id
    title
  }
}

Мой вопрос: как мне импортировать этот файл в мой компонент без необходимости превращать его в код JavaScript?Я имею в виду, я не хочу использовать любой не-GraphQL-код в моем файле .graphql (поэтому нет module.exports export default и т. Д.).

Вот все, что я пробовал:

Использование веб-пакета :

/* 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,
  },
})));

Эта установка выдает следующую ошибку (отказывается даже распознавать загрузчик!):

. /apollo / test.graphql 2: 8 Ошибка синтаксического анализа модуля: неожиданный токен (2: 8) Вам может потребоваться соответствующий загрузчик для обработки этого типа файла, в настоящее время загрузчики не настроены для обработки этого файла.См. https://webpack.js.org/concepts#loaders |{сообщения {|_id |title

Использование Babel :

Я добавил плагин babel-plugin-import-graphql babel (yarn add -D babel-plugin-import-graphql к моим зависимостям dev).Затем обновил мой .babelrc следующим образом:

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

Это приводит к следующей ошибке:

Произошла ошибка построения {Инвариантное нарушение: Аргумент {posts {_id title primaryTitle}}передан в синтаксический анализатор не был действительным GraphQL DocumentNode.Возможно, вам понадобится использовать 'graphql-tag' или другой метод для преобразования вашей операции в документ с неизменным (/home/ubuntu/proost/web-no-apollo/node_modules/invariant/invariant.js:40:15)

Любой третий вариант?

1 Ответ

0 голосов
/ 19 сентября 2019

Вам нужен такой пакет, как Webpack, который позволяет вам определять, как загружать .graphql файлы.Затем вы просто импортируете файл graphql и используете результирующую строку / объект запроса, как и раньше.

Одна из возможностей - webpack-graphql-loader , но Apollo рекомендует , используя graphql-tag .

В любом случае, вы можете попробовать этот подход специально для Next.js .

...