Skip to content

Update ts-bridge and Build Pipeline for React Native Packages #702

Closed
@georgewrmarshall

Description

@georgewrmarshall

Background

Previously, the React Native packages (@metamask/design-system-react-native and @metamask/design-system-twrnc-preset) were using tsc directly for building instead of the monorepo's standard ts-bridge build system. This was due to a known issue with ts-bridge not properly handling React Native's index.js file which contains Flow code rather than plain JavaScript.

Root Cause: ts-bridge issue #72 - React Native's index.js file contains Flow code, which caused ts-bridge's import rewriting to fail when the file couldn't be parsed by cjs-module-lexer.

Resolution: This issue was fixed in ts-bridge PR #73 which handles export detection errors gracefully by leaving imports as-is when packages cannot be parsed.

Objectives

  1. Standardize Build System: Migrate React Native packages to use ts-bridge for consistency with the rest of the monorepo
  2. Update Package Configuration: Align package.json exports and scripts with other packages
  3. Simplify Build Pipeline: Remove custom build scripts and configurations
  4. Update Constraints: Remove React Native-specific exceptions from yarn constraints
  5. Improve Test Configuration: Update Jest configuration for better test handling

Changes Made

1. Package Configuration Updates

@metamask/design-system-react-native

  • ✅ Updated package.json to use ts-bridge build script
  • ✅ Standardized exports format to dual module (ESM/CJS) structure
  • ✅ Removed custom scripts/build.js file
  • ✅ Updated tsconfig.build.json for ts-bridge compatibility
  • ✅ Fixed TypeScript configuration to resolve React Native type conflicts

@metamask/design-system-twrnc-preset

  • ✅ Updated package.json to use ts-bridge build script
  • ✅ Standardized exports format to dual module (ESM/CJS) structure
  • ✅ Updated Jest configuration with passWithNoTests: true
  • ✅ Adjusted coverage thresholds to realistic levels

2. Build System Improvements

Before (using tsc):

{
  "scripts": {
    "build": "node scripts/build.js"
  }
}

After (using ts-bridge):

{
  "scripts": {
    "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references"
  }
}

3. Exports Standardization

Both packages now use the standard dual module format:

{
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.mts",
        "default": "./dist/index.mjs"
      },
      "require": {
        "types": "./dist/index.d.cts",
        "default": "./dist/index.cjs"
      }
    }
  }
}

4. Yarn Constraints Cleanup

Removed React Native-specific exceptions from yarn.config.cjs:

  • ✅ Removed export validation exceptions
  • ✅ Removed test script exceptions
  • ✅ All packages now follow the same constraints

5. Preview Build Script Cleanup

Updated scripts/prepare-preview-builds.sh:

  • ✅ Removed React Native-specific TypeScript import handling
  • ✅ Simplified the build process since all packages now use the same build system

6. TypeScript Configuration

React Native Package (tsconfig.build.json):

{
  "extends": "../../tsconfig.packages.build.json",
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist",
    "rootDir": "./src",
    "jsx": "react-native",
    "types": ["react-native", "jest"],
    "skipLibCheck": true,
    "esModuleInterop": true,
    "moduleResolution": "Node16"
  },
  "references": [
    { "path": "../design-system-twrnc-preset/tsconfig.build.json" }
  ],
  "include": ["./src", "global.d.ts"]
}

7. Jest Configuration Improvements

TWRNC Preset (jest.config.js):

module.exports = merge(baseConfig, {
  displayName,
  passWithNoTests: true,
  coverageThreshold: {
    global: {
      branches: 75,
      functions: 70,
      lines: 84,
      statements: 84,
    },
  },
  // ... React Native specific configurations
});

Verification

Build Verification

# Individual package builds
yarn workspace @metamask/design-system-react-native build
yarn workspace @metamask/design-system-twrnc-preset build

# Full monorepo build
yarn build

# Test execution
yarn workspace @metamask/design-system-twrnc-preset test

Output Structure

Both packages now generate the correct dual module format:

dist/
├── index.cjs          # CommonJS bundle
├── index.d.cts        # CommonJS type definitions
├── index.mjs          # ES Module bundle
└── index.d.mts        # ES Module type definitions

Benefits

  1. Consistency: All packages now use the same build system and configuration patterns
  2. Maintainability: Reduced custom build scripts and configurations
  3. Type Safety: Improved TypeScript configuration and dual module support
  4. Developer Experience: Simplified build process and better error handling
  5. Future-Proof: Aligned with ts-bridge improvements and React Native compatibility

Dependencies

  • @ts-bridge/cli: ^0.6.3 (includes the React Native fix)
  • React Native type definitions properly configured
  • Updated yarn constraints validation

Testing

  • ✅ All packages build successfully with ts-bridge
  • ✅ Dual module outputs are generated correctly
  • ✅ Yarn constraints pass without exceptions
  • ✅ Tests run successfully with updated Jest configuration
  • ✅ Preview build script works without React Native-specific handling

Related Issues

Impact

This change brings the React Native packages in line with the rest of the monorepo's build system, eliminating technical debt and improving maintainability. The migration was made possible by the resolution of the underlying ts-bridge compatibility issue with React Native.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions