Skip to content

Preview: Codegen Field Merging

Pre-release
Pre-release
Compare
Choose a tag to compare
@AnthonyMDev AnthonyMDev released this 02 Aug 19:10
· 30 commits to main since this release

This is a preview release of a new feature that improves the code generation engine's field merging algorithm and allows for disabling of field merging altogether. The feature work for this preview version is being tracked in issue #2560.

Reduced Generated Code Size of Merged Selection Sets

The code generation algorithm is now able to recognize most situations where a merged selection set is a direct copy of a selection set that is being merged. In those cases, it now uses a typealias referencing the original selection set rather than generating a duplicate. This is most commonly seen for the child entities of a named fragment that is spread into another selection set. In some cases this can dramatically decrease the size and complexity of the generated models.

Bug Fix: Generated Selections Sets in Inclusion Condition Scope

This also fixes a bug when using @include/@skip where generated models that should have been generated inside of a conditional inline fragment were generated outside of the conditional scope. This may cause breaking changes for a small number of users. Those breaking changes are considered a bug fix since accessing the conditional inline fragments outside of the conditional scope could cause runtime crashes (if the conditions for their inclusion were not met).

Disabling Field Merging

If you need to further reduce the size of generated models, you can use the new experimental field merging configuration option to disable field merging.

The field merging feature has three types of merging that you can enable or disable selectively:

  • Ancestors: Merges fields and fragment accessors from the selection set's direct ancestors.
  • Siblings: Merges fields and fragment accessors from sibling inline fragments that match the selection set's scope.
  • Named Fragments: Merges fields and fragment accessors from named fragments that have been spread into the selection set.

Limitations

Disabling of field merging is incompatible with the inclusion of selectionSetInitializers. Because the generated initializers require fully formed objects with all field merged into them in order to ensure the generated objects are valid for each of their type cases. It is likely that this limitation will not be able to be resolved in the future. However we hope the new merging algorithm additions will provide enough of an improvement to the generated models to make disabling of field merging unnecessary for most users.

Configuration - JSON

To enable this option when using a json config file, use the configuration option experimentalFeatures.fieldMerging.

{
        "experimentalFeatures" : {
          "fieldMerging" : [
            # Any combination of these values:
            "siblings",
            "ancestors",
            "namedFragments"
          ],
          "legacySafelistingCompatibleOperations" : true
        },
        "input": {
# ...

You may also input fieldMerging: [ "all" ], to enable all types of field merging (which is the default value if not provided).

Configuration - Scripting with ApolloCodegenLib

To enable this option when using the ApolloCodegenLib directly, set the ApolloCodegenConfiguration.experimentalFeatures.fieldMerging option.

config = ApolloCodegenConfiguration(
    schemaNamespace: "MySchema,
    input: // ...,
    output: // ...,
    options: // ... ,
    experimentalFeatures: .init(
        fieldMerging: [
            # Any combination of these values:
            .siblings,
            .ancestors,
            .namedFragments
        ]
    )
)

You may also input fieldMerging: .all, to enable all types of field merging (which is the default value if not provided).

Known Issues

There is a longstanding bug (since Apollo iOS 1.0) in the codegen engine for some users that have large sets of operations with many deeply nested fragment spreads. For these users, the codegen engine never finishes running, using unbounded memory and eventually crashing once it has used all available memory. This version does not resolve this issue, but we are hoping to address this in a release in the near future!

Testing

Because the changes to the generated models in this version can be large in some circumstances, we would like to get feedback on any issues you encounter while using this preview version before we release this into a stable version of Apollo iOS. Please file an issue for any problems you encounter.

Issues may appear when using the new disabling of field merging, but we are also aware of possible issues when not using this new feature (ie. fieldMerging: .all)

We are particularly concerned about possible issues in the following situations:

  • GraphQL Definitions with deeply nested named fragments spreads
  • Complex uses cases with @include/@skip conditions

In addition to feedback on problems you encounter, we would also love to hear about your success stories! If this new version works well for you and reduces the size of your generated models in a meaningful way, please let us know in #2560!

Thank you for trying out this preview version of Apollo iOS. We appreciate your time and effort as well as any feedback you can provide.