Description
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
- Standardize Build System: Migrate React Native packages to use
ts-bridge
for consistency with the rest of the monorepo - Update Package Configuration: Align
package.json
exports and scripts with other packages - Simplify Build Pipeline: Remove custom build scripts and configurations
- Update Constraints: Remove React Native-specific exceptions from yarn constraints
- 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 usets-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 usets-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
- Consistency: All packages now use the same build system and configuration patterns
- Maintainability: Reduced custom build scripts and configurations
- Type Safety: Improved TypeScript configuration and dual module support
- Developer Experience: Simplified build process and better error handling
- 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
- ts-bridge/ts-bridge#72 - Original React Native compatibility issue
- ts-bridge/ts-bridge#73 - Fix for export detection errors
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.