Ignored tokens in GraphQL
The GraphQL specification defines a set of “ignored tokens” that carry no meaning: whitespace, line terminators, comments starting with #, the optional byte-order mark and, less obviously, commas. Commas in GraphQL are purely cosmetic, so customer { name, email } and customer { name email } are the same selection, and so are ($first: Int, $status: OrderStatus) and the same arguments without the comma. The minifier removes every ignored token it can. A space is only kept where two names or numbers would otherwise run together, such as name email. Punctuation never needs one, which is why $first:Int=20$status:OrderStatus is still valid.
The work is done by stripIgnoredCharacters from graphql-js, the reference implementation that most JavaScript servers and clients build on. Because it operates on the lexer’s tokens rather than with regular expressions, it cannot confuse a # inside a string with a comment.
Where a minified document helps
- GET requests and CDN caching. Sending queries as a URL parameter keeps them cacheable, but URLs have practical length limits; the dashboard query in the first example shrinks from 251 to 133 bytes.
- Persisted queries and APQ. Automatic persisted queries identify a document by its SHA-256 hash. Minifying every query the same way before hashing means a reformat in your editor does not create a new hash and a cache miss.
- Embedding in JSON or code. A one-line query is easier to put in a JSON request body, a curl command or a test fixture without escaping newlines.
- Logs and metrics. Operation text in traces is shorter and groups consistently.
Most GraphQL servers also accept formatted queries, so minify for transport and keep the readable version in source control.
What is preserved
Everything with meaning stays. String arguments keep their exact contents, including spaces and commas inside the quotes, so text: "Leave at the door, thanks" is untouched. Block strings ("""), used for schema descriptions, keep their lines and relative indentation; at most, blank lines at the start or end that GraphQL strips from the value anyway are removed. Operation names, aliases, variables with default values, directives such as @include(if: $withItems), fragments and inline fragments all survive. Numbers, enum values and argument order are copied exactly. Schemas minify too: type, enum, input and directive definitions in SDL go through the same rules, and the descriptions remain attached to their types.
Because comments are ignored tokens, they are always removed. If a comment holds something a tool reads, such as an annotation for a code generator, minify a copy rather than the source file.
Validation before output
The document is parsed by Prettier’s GraphQL parser before stripping, so an unclosed brace, an unterminated string or a stray token is reported as a graphql-js “Syntax Error” with its position, and no output is produced. Only syntax is checked; whether fields exist is a question for your schema and server. Use Ctrl/Cmd+Shift+M to compare with the formatted version, and Ctrl/Cmd+Shift+C to copy. Queries are processed inside the page, which keeps internal API shapes private.
Examples
Commented query with commas
The comment, the commas and all indentation are removed, roughly halving the size of the document.
# Dashboard query used by the orders page
query RecentOrders($first: Int = 20, $status: OrderStatus) {
orders(first: $first, status: $status) {
edges {
node {
id,
total,
customer { name, email }
}
}
}
}
query RecentOrders($first:Int=20$status:OrderStatus){orders(first:$first status:$status){edges{node{id total customer{name email}}}}}Schema with a block string description
SDL is minified like operations: the description keeps its indented line, while the # comment and enum commas disappear.
"""
An order placed in the shop.
Indented text in a block string is kept.
"""
type Order {
id: ID!
# internal note
status: OrderStatus!
items: [OrderItem!]!
}
enum OrderStatus { PENDING, PAID, SHIPPED }
"""
An order placed in the shop.
Indented text in a block string is kept.""" type Order{id:ID!status:OrderStatus!items:[OrderItem!]!}enum OrderStatus{PENDING PAID SHIPPED}Mutation with spaces inside a string
The comma between arguments goes, but the comma and repeated spaces inside the text value are part of the data and stay.
mutation { addNote(orderId: "ord_8f2k1", text: "Leave at the door, thanks") { id } }mutation{addNote(orderId:"ord_8f2k1" text:"Leave at the door, thanks"){id}}Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Syntax Error: Expected Name, found <EOF>. | The document ends while a selection set is still open, typically a missing closing brace. | Add the missing } so every { has a partner. The position is the end of the input. |
Syntax Error: Expected Name, found "{". | An argument list was not closed before the selection set started, as in user(id: 1 { name }. | Close the parenthesis: user(id: 1) { name }. |
Syntax Error: Unterminated string. | A string argument opens with a double quote that is never closed on the same line. | Add the closing quote, or use a “”" block string for text that spans lines. |
Syntax Error: Unexpected "}". | There is one closing brace too many after the operation. | Remove the extra } at the reported column. |
Frequently asked questions
Are commas required in GraphQL?
No. The specification treats commas as ignored tokens, like whitespace, so the minifier removes them and the query means exactly the same.
Does minifying a GraphQL query change the result?
No. Only ignored tokens are removed, and stripIgnoredCharacters is designed so the stripped document parses to the same operations, fields and values.
Can I minify a schema (SDL) as well as queries?
Yes. Type definitions, enums, inputs and directives are all GraphQL documents, and descriptions written as strings are kept.
How do I make a minified query readable again?
Switch to Beautify or use the GraphQL formatter. Comments removed during minification cannot come back.