Comparison to graphql_core V3
Version 3 of the graphql
module shipped with graphql_core
, which was also a ready-to-use schema generator.
This module can be seen as the successor to graphql_core
, but it introduces a few key differences:
Opt-in Approach
In graphql_core, it was not easy to define which entity types and fields should be included in the schema. However, in the new module, everything is opt-in by default, allowing for more control over what gets included.
entityById and entityQuery
Previously a byId and query field was generated for every entity type. This quickly results in a lot of duplication - 20 entity types result in 40 query fields.
This has changed to two generic entity query fields: entityById
and entityQuery
. Both take a required argument called entityType
.
Reverse Entity Query
This is the process of querying for entities that reference the current entity. In graphql_core a field was generated for every entity_reference field on every entity type. This added potentially hundreds of fields to the schema that are likely never used:
type MediaFile {
reverseFieldMediaScreenshotNode(
filter: EntityQueryFilterInput = null
limit: Int = 10
offset: Int = 0
revisions: EntityQueryRevisionMode = DEFAULT
sort: [EntityQuerySortInput] = null
): EntityQueryResult!
}
This feature is now opt-in via the Reverse Entity Reference extension.
It only adds a single field called reverseReference
on each entity:
type MediaFile {
reverseReference: ReverseReferenceContext
}
There it's possible to execute reference lookup queries by providing the target fields yourself.
Here's how this compares:
query {
mediaById(id: "5") {
... on MediaFile {
reverseFieldMediaScreenshotNode {
items {
label
}
}
}
}
}
Now you would write it like this:
query {
entityById(entityType: MEDIA, id: 5) {
reverseReference {
query(referenceFields: ["field_media_screenshot"], entityType: NODE) {
items {
label
}
}
}
}
}
Generic Field Types
In graphql_core, a separate type was generated for each entity + field type combination. For example, if there were two entity reference fields:
graphql_core
type NodePage {
fieldTeaserMedia: FieldNodePageFieldTeaserMedia
}
type NodeArticle {
fieldTeaserMedia: FieldNodeArticleFieldTeaserMedia
}
type FieldNodePageFieldTeaserMedia {
entity: Media
targetId: Int
}
type FieldNodeArticleFieldTeaserMedia {
entity: Media
targetId: Int
}
This made it very hard to write fragments for a specific field type because they didn't share a common interface.
graphql_core_schema
Now, the field type is generated only once and is used for all fields with the same type.
Additionally, the field is added twice, with one always resolving to the referenced entity, providing a sensible and useful value. For example:
type NodePage {
fieldTeaserMedia: MediaImage
fieldTeaserMediaRawField: FieldItemListEntityReference
}
type NodeArticle {
fieldTeaserMedia: MediaImage
fieldTeaserMediaRawField: FieldItemListEntityReference
}
type FieldItemListEntityReference implements FieldItemList {
isEmpty: Boolean!
first: FieldItemTypeEntityReference
list: [FieldItemTypeEntityReference]
}
Improved Interfaces
The interfaces provided in graphql_core were verbose and repetitive. However, the new module offers only three entity interfaces, and the fields for the Entity
interface are configurable. For example:
interface Entity {
id: String
label: String
}
interface EntityLinkable {
url(rel: String): Url
}
interface EntityTranslatable {
translation(fallback: Boolean, langcode: Langcode!): EntityTranslatable
translations: [EntityTranslatable]
}
Reduced Schema Size
Thanks to the configurability of entity types and fields, as well as the use of generic field types, the schema size is significantly smaller compared to graphql_core.
Extensibility
With the introduction of generic field types and smaller interfaces, it is now much easier to extend generated types with less code required. Furthermore, the module is fully compatible with version 4 of the GraphQL module.