'serve html file from node_modules using react native static server and webview

Is it possible to serve an html file from within the node_modules folder? I know how to serve from the assets folder, something like:

<WebView 
  ...
  source={{uri:'file:///android_asset/project_a/index.html'}}/>

or the corresponding path for iOS, but how can I access the node_modules folder and serve a file from there? I've tried using require() and/or using the path to the module I want served but with no luck.

The idea is that, I want to avoid copy-pasting build files between projects (i.e., from the build folder of project A to the assets/www of project B), instead, I want publish project A as an npm package and npm install and serve it from project B. This also improves version management of the projects.



Solution 1:[1]

I ended up adding a script to packages.json that copies the files of interest into the assets/www folder before starting the app. Something like:

"scripts": {
    "copy:build": "node -e \"fs.copyFileSync('./node_modules/dir-of-module','./assets/www/build')\"",
    "start-android": "npm run copyAssets && react-native run-android",
    ...
  }

If there is a better alternative, please let me know!

Solution 2:[2]

For Android, you can run a custom Gradle task that able to will handle copy your assets in build time.

Create a Gradle file in your module's root, like below:

(I presume your module name is react-native-my-awesome-module and your HTML files is under www folder in module's root.)

awesome.gradle:

/**
 * Register HTML asset source folder
 */
android.sourceSets.main.assets.srcDirs += file("$buildDir/intermediates/ReactNativeMyAwesomeModule")

/**
 * Task to copy HTML files
 */
afterEvaluate {
    def targetDir = "../../node_modules/react-native-my-awesome-module/www";
    def fileNames = [ "*.html" ];

    def htmlCopyTask = tasks.create(
        name: "copyReactNativeMyAwesomeModuleAssets",
        type: Copy) {
        description = "copy react native my awesome module assets."
        into "$buildDir/intermediates/ReactNativeMyAwesomeModule/www"

        fileNames.each { fileName ->
            from(targetDir) {
                include(fileName)
            }
        }
    }

    android.applicationVariants.all { def variant ->
        def targetName = variant.name.capitalize()
        def generateAssetsTask = tasks.findByName("generate${targetName}Assets")
        generateAssetsTask.dependsOn(htmlCopyTask)
    }
}

After installing the module, put the below line in your project's android/app/build.gradle file:

apply from: file("../../node_modules/react-native-my-awesome-module/awesome.gradle"); 

When you build your app, your assets under www folder will be copied from your module. You can access your resources in your app like below :

<WebView 
  source={{uri: 'file:///android_asset/www/index.html'}}
/>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 N. Doe
Solution 2