Skip to content
This repository has been archived by the owner on May 10, 2021. It is now read-only.
/ babel-gql Public archive

Persisted GraphQL Query Compiler for Babel and a tiny GraphQL client.

Notifications You must be signed in to change notification settings

valu-digital/babel-gql

Repository files navigation

MOVED

To the npm-package monorepo https://github.com/valu-digital/npm-packages

babel-gql

Persisted GraphQL Query Compiler / Generator for Babel and Webpack and a tiny GraphQL client. It generates persisted query files automatically within your Babel/Webpack compilation without any extra watchers.

Install

npm install babel-gql

Add babel-gql/plugin to your babel plugins. Ex.

babel.config.js:

module.exports = {
    presets: ["@babel/preset-env"],
    plugins: ["babel-gql/plugin"], // <-- add this
};

Add BabelGQLWebpackPlugin to webpack.config.js

const { BabelGQLWebpackPlugin } = require("babel-gql/plugin");

module.exports = {
    // ...
    plugins: [
        new BabelGQLWebpackPlugin({
            // the directory where persisted query files will be written to
            target: ".queries",
        }),
    ],
};

If you use @valu/webpack-config:

// v0.12.0 or later
const { createWebpackConfig } = require("@valu/webpack-config");
const { BabelGQLWebpackPlugin } = require("babel-gql/plugin");

module.exports = createWebpackConfig({
    babelPlugins: ["babel-gql/plugin"],
    webpackPlugins: [
        new BabelGQLWebpackPlugin({
            target: ".queries",
        }),
    ],
});

Usage

import { gql, request } from "babel-gql";

const getPostsQuery = gql`
    query getPosts($first: Int) {
        posts(first: $first) {
            nodes {
                title
                content
            }
        }
    }
`;

request("/graphql", {
    query: getPostsQuery,
    variables: {
        first: 10,
    },
}).then(res => {
    console.log(res.data);
});

When compiled to development the request() will send a POST request with the query to the given endpoint.

It basically does this

fetch("/graphql", {
    method: "post",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
        variables: {
            first: 10,
        },
        query:
            "query getPosts($first: Int) { posts(first: $first) { nodes { title content } } }",
    }),
});

but when compiled to the production (NODE_ENV=production) the actual GraphQL query will be completely removed from the bundle and the request() will send a GET request with a hash of the query using the persistedQuery extension:

GET /graphql?operationName=getPosts
    &variables={"first":10}
    &extensions={"persistedQuery":{"version":1,"sha256Hash":"fc97c4a5683a1c5d521aba0b11a305bfa13e4cded69bf4559cca6e2b6e4c6102"}}

To make this work for the backend the plugin will generate a .queries directory with the actual queries

ls .queries/
getPosts-fc97c4a5683a1c5d521aba0b11a305bfa13e4cded69bf4559cca6e2b6e4c6102.graphql

The backend must implement this extension too and be able to load the query from the file.

WPGraphQL

If you are using WPGraphQL with WordPress you can use the wp-graphql-lock extension to implement this via pre_graphql_lock_load_query filter:

add_filter( 'pre_graphql_lock_load_query', function(  $query,  $query_id, $query_name ) {
	$query_dir = realpath( __DIR__ . '/.queries' );
	$full_path = realpath( $query_dir . "/$query_name-$query_id.graphql" );

	// Check for ../../ attacks
	if (strpos($full_path, $query_dir) !== 0) {
		return null;
	}

    return file_get_contents($full_path);
}, 10, 3 );

This assumes that .queries is commited to git in your theme directly and the above code is in functions.php.

Usage with React

This does not contain anything React specific but there are multiple React Hooks that can work with Async Functions. Here's few: