Remote Dependencies
Zephyr implements a comprehensive dependency resolution system that enables micro-frontend applications to dynamically resolve and load their dependencies at build time, eliminating the need for hardcoded remote URLs and manual version coordination between teams.
In a micro-frontend architecture, applications are composed of multiple independent frontend modules that can be developed and deployed separately. Remote dependencies are other micro-frontend modules that your application needs to function - think of them as external components or services that your app imports and uses at runtime.
The dependency management system operates through a combination of build-time analysis and intelligent resolution strategies. During the build process, Zephyr plugins capture contextual information about the build environment and use this data to resolve abstract dependency declarations into concrete URLs and versions.
Want to control which version of a remote your environment consumes without rebuilding? Check out Environment-Level Overrides to learn how to dynamically override remote dependencies per deployment environment.
Overview
- Understanding Application UIDs
- Configuration
- Version Selectors
- Build Context & Resolution
- Best Practices
Dependency Resolution Architecture
The resolution engine implements a multi-strategy approach to dependency resolution, attempting different resolution methods in a deterministic order until a valid dependency is found. Applications can adapt to various deployment scenarios without configuration changes.
Each resolution strategy is designed for specific use cases:
- Workspace resolution enables automatic version matching based on build context
- Semantic versioning provides fine-grained control over acceptable version ranges
- Label-based resolution allows targeting specific deployment stages
- Platform-specific resolution ensures correct implementations for different runtime environments
The system maintains backward compatibility while enabling advanced workflows that were previously difficult to implement in distributed architectures.
Understanding Application UIDs
Before working with dependencies, it's essential to understand how Zephyr identifies applications. Every application has a unique Application UID following this structure:
Where:
- application: The
namefield from the remote application'spackage.json - project: The git repository name
- organization: The GitHub/GitLab organization or username
For example, if you have:
package.jsonname:"ui-components"- Repository:
design-system - Git organization:
my-company
The Application UID would be: ui-components.design-system.my-company
Learn more: See the Architecture guide for detailed information about Application UIDs and how they're used throughout Zephyr's infrastructure.
Zephyr Dependencies Configuration
Zephyr provides a dependency management system through the zephyr:dependencies field in your package.json to specify remote module federation dependencies that your application needs.
Basic Usage
Add a zephyr:dependencies field to your package.json to specify remote applications your module depends on:
You will see more examples later in this guide
Understanding Dependency Mapping
In the zephyr:dependencies configuration, there are three key concepts:
- Local Name (left side): The name you'll use in your code to import the remote module (e.g.,
header,shoppingCart) - Application UID (right side, before @): The remote application's identifier (e.g., if they are in the same repository as host app, use
ui-library, if they are in different repositories, usecart-service.repo-name.org-name) - Version Selector (right side, after @): The version constraint (e.g.,
latest,stable,v2.1)
The mapping works as follows:
The zephyr: prefix is optional. Both "ui-library@latest" and "zephyr:ui-library@latest" work identically, as zephyr is the default registry. While the prefix is currently optional, we recommend including it for future compatibility when Zephyr supports multiple registries (e.g., npm:, github:, or custom enterprise registries).
The zephyr:dependencies field serves to:
- Declare which remote applications your module depends on
- Create local aliases for remote applications, mapping the local name in your module federation configuration to the remote application name.
- Map remote applications from different repositories or organizations
- Enable Zephyr to validate that dependencies exist and are accessible
- Support multiple version resolution strategies for different deployment scenarios
Supported Declaration Formats
Zephyr's dependency resolution engine supports multiple version selector formats, each designed for specific use cases in your development and deployment workflows.
Label-Based Selectors (Tags and Environments)
Label-based selectors resolve to environments, tags, or version numbers with matching names. They allow you to:
- Target lifecycle stages:
@latest,@stable,@next - Reference specific releases:
@v2.1,@release-3.0 - Use environment names:
@production,@staging,@development - Resolve to specific versions:
@1.2.3,@2.0.0
Resolution Priority: Zephyr searches for an environment with the label name first, then falls back to searching for a tag with that name, and finally attempts to match it as a version number. Environments always take precedence over tags when both exist with the same name.
Semantic Version Ranges
For more precise version control, Zephyr supports the full semver specification:
The selectors provide fine-grained control:
^1.2.3- Compatible with version 1.2.3 (allows 1.x.x updates)~2.0.0- Approximately equivalent to 2.0.0 (allows 2.0.x updates)1.5.0- Exact version match only>=1.0.0 <2.0.0- Any version within the specified range
Zephyr uses the official semver specification for version matching. When multiple versions match a range, the highest matching version is selected.
Wildcard Version
The wildcard "*" selector resolves to the latest available version of a dependency:
The "*" wildcard:
- Returns the latest application version for the target platform
- Falls back to web platform if no versions exist for the requested platform
- Falls back to the default environment if no versions are found
- Unlike
workspace:*, does not match by build context (branch, CI, username) - Provides a simpler syntax for cases where the latest version is always acceptable
Workspace Resolution
The most powerful feature of Zephyr's dependency system is workspace resolution - the ability to automatically resolve dependencies based on your current build context:
When you use workspace:*, Zephyr intelligently resolves dependencies by matching all of the following build context criteria:
- Git branch: The current branch name (e.g.,
feature/new-ui,main) - Target platform: The build target platform (e.g.,
web,ios,android) - CI environment: Whether the build is running in CI (
true) or locally (false) - Username: The developer username or CI identity
The resolution returns the most recent version (by creation date) that matches all four criteria. If no exact match is found, it falls back to the default environment.
To further understand how fallback refer to Default Environment Fallback section.
Key Benefits:
- Feature branches automatically use matching versions of dependencies
- Local development builds are isolated from CI builds
- Each developer can work independently without version conflicts
- Eliminates the need for manual version updates during development
- Updates automatically when rebuilding with the same context
Example: Multi-Remote Setup
In your code, you would import these as:
Cross-Repository Dependencies
When depending on applications from different repositories or organizations, use the full Application UID format to avoid ambiguity:
Use the full UID format when:
- The remote application is in a different repository
- The remote application is in a different organization
- You need to disambiguate between applications with the same name
Build Context and Dynamic Resolution
The dependency resolution system leverages build context to enable dynamic version selection based on environmental factors. A single codebase can resolve to different dependency versions depending on the build environment, target platform, and deployment context.
Build Context Architecture
The build context represents a structured collection of environmental metadata that the resolution engine uses to make deterministic version selections:
The Zephyr plugins automatically capture this context during the build initialization phase. The resolution engine then uses these values to select appropriate dependency versions through pattern matching and fallback chains.
Platform-Specific Resolution
The resolution engine implements platform-aware dependency selection, allowing applications to receive platform-optimized implementations of their dependencies:
The platform resolution follows a hierarchical approach:
- Web platform: Default target, optimized for browser environments
- React Native platform: Mobile-specific implementations with native module support
- Node.js platform: Server-side implementations without browser dependencies
The resolution engine implements automatic fallback to the 'web' platform when platform-specific versions are unavailable, ensuring build reliability while maintaining platform optimization when available.
Label-Based Resolution (Environments and Tags)
Dependencies can be resolved using labels that correspond to environments, tags, or version numbers. When using label-based selectors, Zephyr follows a specific priority order:
Resolution Priority:
- Environment name first: Zephyr searches for an environment with the matching name
- Tag name second: If no environment is found, searches for a tag with the matching name
- Version number third: If no tag is found, attempts to match it as a version number
- Platform fallback: If not found for the target platform, tries the web platform
- Default environment: Falls back to the default environment if no match is found
This priority system means environment names always take precedence over tag names, and tag names take precedence over version numbers. For example, if both an environment and a tag are named production, the environment will be selected.
Resolution Order and Strategies
The resolution engine processes dependency declarations through a deterministic pipeline of resolution strategies. Each strategy uses specific matching criteria and fallback chains to maximize resolution success.
Resolution Pipeline
The resolution strategy is determined by the version selector format:
-
Workspace Resolution (
workspace:*):- Matches application versions by build context: branch name, target platform, CI environment, and username
- Returns the most recent version matching all context criteria
- Falls back to default environment if no matching build is found
- Updates automatically on rebuild with matching context
-
Wildcard (
*):- Returns the latest available application version for the target platform
- Falls back to web platform if no versions exist for the requested platform
- Falls back to default environment if no versions are found
- Similar to
workspace:*but doesn't require matching build context
-
Semantic Version Range (e.g.,
^1.0.0,~2.1.0,>=1.0.0 <2.0.0):- Matches application versions by semver specification
- Selects the highest version matching the range
- Falls back to web platform if no matching version exists for the requested platform
- Falls back to default environment if no matching versions are found
-
Label-Based Resolution (e.g.,
@production,@staging,@latest,@1.2.3):- First searches for an environment with the matching name
- If no environment found, searches for a tag with the matching name
- If no tag found, attempts to match it as a version number
- Environment names take priority over tag names, and tag names take priority over version numbers
- Falls back to web platform if no match exists for the requested platform
- Falls back to default environment if no matching label is found
-
Unrecognized Selectors (invalid or arbitrary values):
- Any selector that doesn't match the above patterns
- Resolves directly to the default environment
- Useful as a fallback strategy for URL-like values
Default Environment Fallback
The default environment is the application's environment with the smallest order value (lowest priority number). This serves as the final fallback for all resolution strategies when:
- No matching versions exist
- Platform-specific versions are unavailable
- Labels or tags cannot be resolved
- Invalid selectors are provided
Applications must have at least one environment created in Zephyr Cloud to be resolvable as dependencies. The environment with the smallest order value becomes the default fallback. Create environments through the Zephyr dashboard after building your application.
Build-Time Behavior
During the build process, Zephyr:
- Captures the current build context automatically
- Parses your
zephyr:dependenciesconfiguration - Resolves each dependency using the resolution strategies above
- Validates that all resolved dependencies are accessible
- Injects the resolved URLs into your module federation configuration
- Generates a dependency manifest for runtime verification
Resolved dependencies are cached during the build process to ensure consistency. If the same dependency is referenced multiple times, it will resolve to the same version throughout the build.
Error Handling and Fallback Chain
The resolution engine implements a multi-level fallback system to maximize resolution success rates:
- Platform fallback: When platform-specific resolution fails, automatically attempts with 'web' platform
- Environment fallback: Falls back to the application's default environment when other strategies fail
- Structured error codes: Returns specific error codes to help diagnose resolution failures
Dependency Graph
Zephyr requires building applications in dependency order - the most distant remotes must be built first to accurately construct the dependency graph. When a dependency cannot be resolved, you'll see detailed error messages:
For applications using multiple remotes, unresolved dependencies will be listed together, helping you identify which applications need to be built first.
Best Practices
The following patterns and strategies optimize dependency resolution for different deployment scenarios and team workflows.
Development Workflow with Workspace Resolution
The workspace:* selector enables automatic local version coordination across branches:
The configuration enables:
- Feature branches resolve to matching feature branch versions of dependencies
- CI/CD environments receive environment-appropriate versions
- Local development automatically uses developer-specific builds
Version Strategy for Production
For production deployments, combine different selectors for optimal stability:
Debugging Resolution Issues
The resolution system provides several mechanisms for troubleshooting dependency resolution failures:
- Version availability verification: Query the available versions for the target application
- Access control validation: Verify organization and project access permissions
- Build context inspection: Enable debug logging to examine captured context values
- Fallback chain analysis: Trace the resolution attempts through each fallback level
Migration Strategies
When migrating existing applications to use advanced selectors:
- Start with explicit versions to establish a baseline
- Gradually introduce semver ranges for stable dependencies
- Adopt workspace resolution for active development
- Use environment labels for deployment-specific versions
You don't need to use all features at once. Start with basic version tags and gradually adopt more sophisticated selectors as your needs grow.
Related Documentation
Core Concepts:
- Versions - Understanding version management and resolution
- Tags & Environments - Label-based deployment strategies
- Environment Overrides - Override dependencies per environment without rebuilding
Implementation Guides:
- Module Federation Guide - Complete guide to micro-frontends with Zephyr
- Architecture - Deep dive into dependency resolution architecture
- Integration Guides - Adding Zephyr to existing applications
Common Patterns
Monorepo Development:
Gradual Rollout: