To the npm-package monorepo https://github.com/valu-digital/npm-packages
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.
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",
}),
],
});
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.
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
.
This does not contain anything React specific but there are multiple React Hooks that can work with Async Functions. Here's few: