javascriptnode.jsreact-nativebrowserifydat-project

Is it possible to shim Node's fs.readFileSync() in React Native?


I want to port a number of packages written for NodeJS to React Native.

For this purpose I created a RN project using the popular Ignite boilerplate, then used the ReactNativify method and shim Node API objects mostly reusing existing browserify shims.

(For details and some useful tips see Can we use nodejs code inside react native application?)

Some Node objects are still replaced with empty mocks after transpilation, such as fs. Done in .babelrc as follows:

    ["module-resolver", {
      "alias": {
        "fs": "./config/mock",
        "sodium-universal": "libsodium"

        // etcetera
      }
    }]

The packages to port contain a number of calls to fs.readFileSync in its transitive dependencies.

For instance in one of them, hypercore-protocol, there is this line of code:

module.exports = protobuf(fs.readFileSync(path.join(__dirname, 'schema.proto'), 'utf-8'))

And here is a problem, because Android and iOS do not support synchronous file transfer. That line looks like it is un-shim-able to me

Now, while there exists a shims for fs: react-native-level-fs it does not implement the synchronous filesystem methods.

Then there are browserify transforms, like brfs, the 'browserify fs.readFileSync() static asset inliner' (and its alternatives bfrs-babel and babel-plugin-static-fs).

But I don't know how to include them, and if they will even work in RN?

So I see four approaches going forward:

  1. Find a way to merge react-native-level-fs and brfs into a usable shim replacement
  2. Write a completely new fs shim, that has all the methods
  3. If synchronous fs impossible (I think it is), then somehow override all occurrences of functions throughout the transitive dependency tree that invoke sync methods, and replace them by js snippets in local codebase
  4. If there are too many occurrences of 3. then decide the package cannot be ported to React Native

I am hoping for 1. and alternatively 3. to be working solutions. Can anyone advise?

For sake of completeness. I am in this stage of life:

System
  platform           linux                                                                                                
  arch               x64                                                                                                  
  cpu                4 cores   Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz                                                        

JavaScript
  node               7.10.1       /usr/local/bin/node  
  npm                4.2.0        /usr/local/bin/npm   
  yarn               0.24.6       /usr/bin/yarn        

React Native
  react-native-cli   2.0.1       
  app rn version     0.45.1      

Ignite
  ignite             2.0.0        /usr/local/bin/ignite  

Android
  java               1.8.0_111    /usr/bin/java  
  android home       -            undefined 

Solution

  • No. There is no reasonable alternative for Node's fs.readFileSync.

    Though technically it is possible to write a readFileSync shim that blocks on an asynchronous file operation, it is inadvisable to force synchronous behavior in an asynchronous system (but you may be able to get away with it, when only having few synchronous methods in one-time initialization code).

    So option 3 or 4 are the only viable alternatives.

    In my case there were too many Node dependencies, so I ditched browserifying / shimming and opted for 4. But ...

    That does not mean all is necessarily lost. I am now investigating Compiling NodeJS as native library in Android

    (And Realm.io to bridge native NodeJS + React Native in Android fat client app (CQRS-style)).