Here's how I did it synchronously in Swift and JS for iOS/tvOS/macOS, based on the React Native docs: Exporting Constants.
Disadvantage: Note that the file will be loaded into memory once upon startup, and won't be dynamically re-loadable.
Advantage: It's synchronous, simple, and works at run-time whether in native or JS.
MyJSFile.js
import { NativeModules } from "react-native";
console.log(NativeModules.MyNativeModule.MyFileContents);
We import our native module and access the MyFileContents
constant that we expose upon it. It works synchronously with no bridge-crossing (as far as I understand, it's injected into the React Native JSContext via JavaScriptCore).
In Build Phases
, ensure that this file is added into Copy Bundle Resources
. Otherwise your app will quickly crash upon trying to read it.
MyNativeModule.swift
import Foundation
@objc(MyNativeModule)
class MyNativeModule: RCTEventEmitter {
@objc override func constantsToExport() -> [AnyHashable : Any]! {
let contents: String = try! String(contentsOfFile: Bundle.main.path(forResource: "MyFile.min", ofType: "js")!)
return [
"MyFileContents": contents
]
}
@objc override func supportedEvents() -> [String]! {
return []
}
@objc override static func requiresMainQueueSetup() -> Bool {
return false
}
}
One can likely make a simpler/slimmer native module than this one (by subclassing something with less functionality than RCTEventEmitter
), but this is the file I had lying around to work with, so here it is.
MyProject-Bridging-Header.h
#import <React/RCTBridge.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTUIManager.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTJavaScriptLoader.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTRootView.h>
#import <React/RCTEventDispatcher.h>
Here's the bridging header I'm using. It exposes a lot more headers than are strictly necessary, but you may need them for other native modules later anyway.
As this approach uses Swift, make sure to enter your Build Settings
and set Always Embed Swift Standard Libraries
to Yes
if you haven't already. And if this is the first time building your app with Swift embedded, you may want to clear DerivedData for luck before building.
... Or simply rewrite that same Swift code in Obj-C, as the documentation shows how.