DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Building Modern 3factor Apps in 2021 With Event-Driven Programming
  • How to Build a Pokedex React App with a Slash GraphQL Backend
  • Optimizing Natural Language Queries for Multi-Service Information Retrieval
  • Designing Scalable Java APIs With GraphQL

Trending

  • Emerging Data Architectures: The Future of Data Management
  • Medallion Architecture: Efficient Batch and Stream Processing Data Pipelines With Azure Databricks and Delta Lake
  • Understanding and Mitigating IP Spoofing Attacks
  • Enhancing Security With ZTNA in Hybrid and Multi-Cloud Deployments
  1. DZone
  2. Data Engineering
  3. Databases
  4. IOS App Modularization With Apollo And SPM

IOS App Modularization With Apollo And SPM

Apollo is a popular GraphQL client due to its robust features. This guide explains the benefits, drawbacks, and modular approach.

By 
Aitor Pagan user avatar
Aitor Pagan
·
Nov. 10, 23 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
2.6K Views

Join the DZone community and get the full member experience.

Join For Free

In the modern development landscape, GraphQL has revolutionized the way we think about APIs and data retrieval. When it comes to iOS development, integrating GraphQL can be a breeze, thanks to libraries like Apollo. But how do you take it a step further and make your implementation modular using Swift Package Manager (SPM)? This article will guide you through the benefits, drawbacks, and step-by-step process of achieving this modular approach.

Why Apollo?

Apollo has become one of the most popular GraphQL clients owing to its robust set of features, including intelligent caching, real-time updates, and a strong type system. But one of its less talked-about advantages is its compatibility with Swift and native support for modularization through SPM.

The Need for Modularization

As applications grow, maintaining clean, reusable code becomes challenging. Modularization, or the process of dividing a program into separate sub-programs, is a strategy to manage this complexity. By creating a separate module for the Apollo GraphQL client, we can:

  • Keep GraphQL-related code isolated from other parts of the app.
  • Reuse the module across multiple projects.
  • Make the codebase easier to manage and understand.

How To Implement a Modular Apollo GraphQL Client

Step 1: Initialize a New Swift Package

In your project directory, run:

 
swift package init --type library GraphQLClient


This command initializes a new Swift package named GraphQLClient.

Step 2: Configuring the Swift Package

Now, let’s create a robust Package.swift that defines our module along with a separate testing target and a plugin for the Apollo CLI.

 
// swift-tools-version: 5.7
import PackageDescription

let package = Package(
    name: "GraphQLClient",
    platforms: [
        .iOS(.v14),
        .macOS(.v10_14)
    ],
    products: [
        .library(
            name: "GraphQLClient",
            targets: ["GraphQLClient"]),
        .library(name: "GraphQLClientTesting",
                 targets: ["GraphQLClientTesting"]),
        .plugin(name: "GenerateApolloCli",
                targets: ["GenerateApolloCli"])
    ],
    dependencies: [
        .package(url: "https://github.com/apollographql/apollo-ios.git",
                 from: "1.3.3")
    ],
    targets: [
        .target(
            name: "GraphQLClient",
            dependencies: [.product(name: "Apollo", package: "apollo-ios")],
            path: "./Sources",
            exclude: ["Tests"],
            swiftSettings: [
                .unsafeFlags(["-suppress-warnings"])
            ]),
        .target(name: "GraphQLClientTesting",
                dependencies: [.product(name: "ApolloTestSupport", package: "apollo-ios")],
                path: "./Sources/Tests"),
        .plugin(
            name: "GenerateApolloCli",
            capability: .command(
                intent: .custom(
                    verb: "apollo-cli-generate", // Verb used from the command line
                    description: "Generates graphql"),
                permissions: [
                    .writeToPackageDirectory(reason: "Generate code for graphql")
                ]),
            dependencies: [
                .product(name: "apollo-ios-cli", package: "apollo-ios")
            ],
            path: "Plugins/GenerateApolloCli"
        )
    ]
)


Within this configuration, we’re defining three significant components:

1. GraphQL Client: GraphQLClient

This serves as our Apollo client, the core engine through which we’ll send GraphQL queries and mutations. By modularizing it, we ensure a clean separation from our application logic, allowing for easy updates and potential reuse across projects.

This target includes dependencies for Apollo and sets the path and exclusions for our source files, ensuring clean navigation and minimal build warnings.

2. Testing Module: GraphQLClientTesting

Aiming for solid testing practices, we separate our testing concerns by establishing a dedicated testing module.

This enables the usage of mock responses, creating a controlled environment for our integration tests and ensuring our app’s logic handles data correctly without making actual API calls.

3. Code Generation Plugin: GenerateApolloCli

Code generation is a pivotal feature in GraphQL development, automating the creation of query structures and types. With Apollo CLI’s code generation and our custom Xcode plugin, we enhance our development workflow.

This plugin allows developers to execute Apollo CLI code generation directly from Xcode, simplifying the process and enhancing productivity by reducing context-switching between the terminal and IDE.

Step 3: Apollo Codegen Configuration

When working with Apollo in Swift, the apollo-codegen-config.json file plays a pivotal role in steering code generation. It configures the Apollo CLI’s operations when it’s generating types and operations for your GraphQL queries. Let’s dissect a sample configuration:

 
{
    "schemaNamespace" : "MyNamespaceGraphql",
    "input" : {
        "operationSearchPaths" : ["**/*.graphql"],
        "schemaSearchPaths" : ["**/*.graphqls"]
    },
    "output" : {
        "testMocks" : {
            "absolute" : {
                "path": "./Sources/Tests/Mocks",
                "accessModifier": "public"
            }
        },
        "schemaTypes" : {
            "path" : "./Sources/GraphQLClient/Generated",
            "moduleType" : {
                "embeddedInTarget": {
                    "name": "GraphQLClient",
                    "accessModifier": "public"
                }
            }
        },
        "operations" : {
            "inSchemaModule" : {}
        }
    }
}


1. Schema Namespace

 
"schemaNamespace" : "MyNamespaceGraphql"


This defines the namespace for the generated schema types, ensuring that your GraphQL types are encapsulated under a dedicated namespace, MyNamespaceGraphql, preventing naming conflicts and ensuring clean integration within your Swift code.

2. Input Configuration

 
"input" : {
    "operationSearchPaths" : ["**/*.graphql"],
    "schemaSearchPaths" : ["**/*.graphqls"]
}


The input section dictates where Apollo should search for .graphql and .graphqls files within your project, allowing you to organize your GraphQL documents flexibly without restricting them to a single directory.

3. Output Configuration

The output section is more granular, controlling the destinations and access levels of generated code and mocks.

  • Test Mocks "testMocks" : { "absolute" : { "path": "./Sources/Tests/Mocks", "accessModifier": "public" } } This subsection ensures that your generated test mocks (mocked data responses for your operations) reside in ./Sources/Tests/Mocks and are publicly accessible, facilitating simplified testing.
  • Schema Types "schemaTypes" : { "path" : "./Sources/GraphQLClient/Generated", "moduleType" : { "embeddedInTarget": { "name": "GraphQLClient", "accessModifier": "public" } } } Here, we guide the Apollo CLI to place generated schema types in ./Sources/GraphQLClient/Generated. Furthermore, by embedding them in the GraphQLClient target with public access, these types can be readily utilized within your GraphQL client module.
  • Operations
    json "operations" : { "inSchemaModule" : {} }
    By leaving inSchemaModule empty, we’re instructing Apollo to generate operation types (query, mutation, and subscription handling types) in the same module as the schema types, ensuring cohesion and ease of access in your Swift code.

Step 4: Incorporating the Schema Definition Language (SDL) for Code Generation

The essence of interacting with a GraphQL API pivots on understanding the API’s schema—its types, queries, mutations, and subscriptions. The Schema Definition Language (SDL) is foundational in this, providing a structural and type definition of the API that Apollo utilizes to generate corresponding Swift code.

Why Is SDL Crucial?

The SDL provides a blueprint of the GraphQL API, describing all possible queries, mutations, and data structures in your API. Without it, Apollo’s codegen tool would lack the necessary context for generating types and operations that align with the API.

Embedding SDL in Your Project

To involve SDL in code generation, ensure the .graphqls file containing the SDL of your GraphQL API is placed in the path specified in your apollo-codegen-config.json.

Step 5: Defining Queries and Mutations With .graphql Files

Crafting and managing your queries and mutations is a quintessential step in shaping your GraphQL interactions and, consequently, the generated code via Apollo. Leveraging .graphql files allows you to articulate the exact operations your app will perform, ensuring Apollo generates only the requisite code.

Formulating .graphql Files

1. Define Precisely
Each .graphql file should encapsulate a single query, mutation, or subscription. This ensures clarity and makes tracking changes in version control systems like git more straightforward.

2. Organize Strategically
Store .graphql files in a logical, hierarchical directory structure that reflects their usage within your app. For instance, grouping all user-related operations within a /user directory.

 
# Example Query in a .graphql File
query GetUser($userID: ID!) {
    user(id: $userID) {
        id
        name
        email
    }
}


Tailoring Code Generation

By specifying the exact operations your app will utilize, Apollo CLI will generate Swift code that is:

  • Minimized: Only necessary types and operations are generated.
  • Optimized: Ensures your app is not burdened with unused code and types, streamlining your binary and minimizing potential points of failure.

Ensure that your .graphql files are stored in the directory specified in your apollo-codegen-config.json, enabling Apollo CLI to locate and utilize them during code generation.

 
"input" : {
    "operationSearchPaths" : ["**/*.graphql"]
}


With your queries and mutations strategically defined and organized, you not only streamline your code generation but also enhance the clarity and maintainability of your operations. The lean, tailored code generated by Apollo ensures your app remains optimized and robust, regardless of the complexity of your GraphQL API.

Your steps, from SDL incorporation to query and mutation definition, provide a seamless and efficient approach to leveraging GraphQL with Apollo in Swift, ensuring your development is not just robust and type-safe but also a pleasurable, coherent experience.

Advantages of Modularization

  • Reusability: The Apollo Client module can be used across multiple projects, saving development time.
  • Maintainability: Isolating the GraphQL code makes it easier to manage and update.
  • Separation of Concerns: It keeps your main application codebase clean and focused.

Drawbacks of Modularization

  • Initial Overhead: The setup process may seem like overkill for smaller projects.
  • Dependency Management: Managing package dependencies can become complex.
  • Versioning: Keeping the module in sync with the main project requires a versioning strategy.

Conclusion

Implementing a modular Apollo GraphQL client via Swift Package Manager not only makes your codebase cleaner but also enhances reusability and maintainability. While there may be some initial setup overhead and additional complexities in dependency management, the long-term benefits often outweigh these drawbacks. By leveraging both Apollo and SPM, you can create robust, modular, and efficient iOS applications.

API Command-line interface GraphQL Simple DirectMedia Layer app Io (programming language)

Published at DZone with permission of Aitor Pagan. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Building Modern 3factor Apps in 2021 With Event-Driven Programming
  • How to Build a Pokedex React App with a Slash GraphQL Backend
  • Optimizing Natural Language Queries for Multi-Service Information Retrieval
  • Designing Scalable Java APIs With GraphQL

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!