A high-performance GraphQL compilation tool built in Rust for building Relay applications with optimized queries and type generation.
—
The Relay Compiler uses a flexible JSON-based configuration system that supports both single-project and multi-project setups with extensive customization options.
The compiler searches for configuration in this order:
--config command-line optionrelay.config.json in current directoryrelay.config.js in current directoryrelay key in package.jsonFor projects with a single GraphQL schema and source directory.
{ .api }
interface SingleProjectConfigFile {
// Required
language: "javascript" | "typescript" | "flow";
// Core paths
src?: string; // Root source directory (default: "")
schema?: string; // Path to schema.graphql (default: "")
artifactDirectory?: string; // Specific output directory
// File handling
excludes?: string[]; // File patterns to ignore
schemaExtensions?: string[]; // Directories with schema extensions
// JavaScript/TypeScript specific
customScalarTypes?: Record<string, string>; // GraphQL scalar to JS type mappings
jsModuleFormat?: "commonjs" | "haste"; // Module format
eagerEsModules?: boolean; // Enable ES modules (default: true)
// Advanced options
persistConfig?: PersistConfig; // Query persistence
featureFlags?: FeatureFlags; // Experimental features
moduleImportConfig?: ModuleImportConfig; // @module directive config
schemaConfig?: SchemaConfig; // Schema interface config
}{
"language": "typescript",
"src": "./src",
"schema": "./schema.graphql",
"artifactDirectory": "./src/__generated__",
"excludes": ["**/node_modules/**", "**/__mocks__/**"]
}For monorepos or projects with multiple GraphQL schemas.
{ .api }
interface MultiProjectConfigFile {
// Required
sources: Record<string, string>; // Path-to-project mapping
projects: Record<string, ProjectConfig>; // Project configurations
// Global options
excludes?: string[]; // Global exclusion patterns
featureFlags?: FeatureFlags; // Global feature flags
generatedSources?: string[]; // Generated file directories
savedStateConfig?: SavedStateConfig; // Watchman saved state
}{
"sources": {
"./apps/web/src": "web",
"./apps/mobile/src": "mobile",
"./packages/shared/src": "shared"
},
"projects": {
"web": {
"language": "typescript",
"schema": "./apps/web/schema.graphql",
"artifactDirectory": "./apps/web/src/__generated__"
},
"mobile": {
"language": "typescript",
"schema": "./apps/mobile/schema.graphql",
"artifactDirectory": "./apps/mobile/src/__generated__"
}
}
}Individual project settings within multi-project configurations.
{ .api }
interface ProjectConfig {
// Core settings
language: "javascript" | "typescript" | "flow";
schema: string; // Schema file path
artifactDirectory?: string; // Output directory
// File handling
excludes?: string[]; // Project-specific excludes
schemaExtensions?: string[]; // Schema extension directories
// Code generation
customScalarTypes?: Record<string, string>; // Scalar type mappings
jsModuleFormat?: "commonjs" | "haste"; // Module format
eagerEsModules?: boolean; // ES modules support
// Advanced features
persistConfig?: PersistConfig; // Persistence configuration
featureFlags?: FeatureFlags; // Feature flags override
}Configure how GraphQL queries are persisted for production optimization.
{ .api }
interface RemotePersistConfig {
url: string; // Persistence endpoint URL
headers?: Record<string, string>; // Additional HTTP headers
params?: Record<string, string>; // Additional POST parameters
concurrency?: number; // Request concurrency limit
includeQueryText?: boolean; // Include query text in response
}Example:
{
"persistConfig": {
"url": "https://api.example.com/persist-query",
"headers": {
"Authorization": "Bearer token",
"Content-Type": "application/json"
},
"concurrency": 10,
"includeQueryText": false
}
}{ .api }
interface LocalPersistConfig {
file: string; // Output file path
algorithm?: "MD5" | "SHA1" | "SHA256"; // Hash algorithm (default: MD5)
include_query_text?: boolean; // Include query in output
}Example:
{
"persistConfig": {
"file": "./persisted-queries.json",
"algorithm": "SHA256",
"include_query_text": true
}
}Enable experimental and advanced compiler features.
{ .api }
interface FeatureFlags {
// Each flag can be: disabled | enabled | { "limited": string[] } | { "rollout": number }
[flagName: string]:
| "disabled"
| "enabled"
| { limited: string[] } // Allowlist of files/projects
| { rollout: number }; // Percentage rollout (0-100)
}{ .api }
interface KeyFeatureFlags {
// Core features
actor_change_support?: FeatureFlagValue; // Actor change feature
allow_output_type_resolvers?: FeatureFlagValue; // Output type resolvers
compact_query_text?: FeatureFlagValue; // Compact query printing
// Fragment features
enable_fragment_argument_transform?: FeatureFlagValue; // Fragment arguments
enable_relay_resolver_mutations?: FeatureFlagValue; // Resolver mutations
// Generation features
text_artifacts?: FeatureFlagValue; // Text artifact generation
generate_typescript?: FeatureFlagValue; // TypeScript generation
// Performance features
skip_redundant_nodes?: FeatureFlagValue; // Skip redundant AST nodes
enable_parallelization?: FeatureFlagValue; // Parallel compilation
}{
"featureFlags": {
"actor_change_support": "enabled",
"compact_query_text": "disabled",
"enable_fragment_argument_transform": {
"rollout": 50
},
"generate_typescript": {
"limited": ["web", "admin"]
}
}
}Configure @module directive behavior for component imports.
{ .api }
interface ModuleImportConfig {
dynamicModuleProvider?: string; // Dynamic import provider function
}Example:
{
"moduleImportConfig": {
"dynamicModuleProvider": "./src/utils/dynamicImport.js"
}
}Configure GraphQL schema interface handling.
{ .api }
interface SchemaConfig {
nodeInterfaceIdField?: string; // Node interface ID field name
nodeInterfaceIdType?: string; // Node interface ID type
connectionInterface?: { // Connection interface config
connectionField?: string;
edgesField?: string;
nodeField?: string;
};
}Example:
{
"schemaConfig": {
"nodeInterfaceIdField": "id",
"nodeInterfaceIdType": "ID!",
"connectionInterface": {
"connectionField": "connection",
"edgesField": "edges",
"nodeField": "node"
}
}
}Configure Watchman saved state for faster incremental builds.
{ .api }
interface SavedStateConfig {
filename?: string; // Saved state file path
config?: string; // Watchman config name
}Example:
{
"savedStateConfig": {
"filename": ".watchman-state",
"config": "relay-compiler"
}
}Override configuration via command-line options:
{ .api }
interface CLIConfig {
src?: string; // Override source directory
schema?: string; // Override schema path
artifact_directory?: string; // Override output directory
}These CLI options take precedence over file-based configuration.
The compiler validates configuration files against a JSON schema. Get the schema:
relay-compiler config-json-schema > relay.schema.json{ .api }
interface ConfigValidationErrors {
"Missing required field": string; // Required field not provided
"Invalid language": string; // Unsupported language option
"Schema file not found": string; // Schema path doesn't exist
"Invalid feature flag": string; // Unknown feature flag
"Circular dependency": string; // Circular project dependencies
}{
"language": "typescript",
"src": "./src",
"schema": "./schema.graphql",
"featureFlags": {
"enable_experimental_features": {
"limited": ["development", "staging"]
}
},
"persistConfig": {
"url": "${PERSIST_ENDPOINT}",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}Note: Environment variable substitution depends on your build process - the compiler itself doesn't perform substitution.
Install with Tessl CLI
npx tessl i tessl/npm-relay-compiler