I\'m trying to load .html
, .js
, .css
files from device\'s local file system into React Native WebView component. I was able to get the
In react native it is now possible to require an HTML file and use it as the source for the web view like this (the path is relative to the react-native file you use it in):
const webapp = require('./webapp/index.html');
and the use it in the WebView like this:
<WebView source={webapp} />
Unfortunately this does not load CSS and JavaScript files, that are referenced in the HTML. A solution could be, to write all the CSS and JS inline (e.g. by using a build process).
I was able to include html5/javascript into project by using { html: , baseUrl: } as source. But to be frank, it's more like a lucky shot.
<WebView source={{ html: HTML, baseUrl: 'web/' }} />
I have index.html, which require pano2vr_player.js and pano.xml to make this code work.
const HTML = `
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="mobile-web-app-capable" content="yes" />
<style type="text/css" title="Default">
body, div, h1, h2, h3, span, p {
font-family: Verdana,Arial,Helvetica,sans-serif;
}
</style>
</head>
<body>
<script type="text/javascript" src="pano2vr_player.js">
</script>
<div id="container" style="width:100%;height:100%;">
<br>Loading...<br><br>
This content requires HTML5 with CSS3 3D Transforms or WebGL.
</div>
<script type="text/javascript">
// create the panorama player with the container
pano=new pano2vrPlayer("container");
window.addEventListener("load", function() {
pano.readConfigUrlAsync("pano.xml");
});
</script>
</body>
</html>`;
class PanoView extends Component {
render() {
return (
<View>
<WebView
style={{ flex: 1, width: 1024, height: 768 }}
source={{ html: HTML, baseUrl: 'web/' }}
javaScriptEnabledAndroid={true} />
</View>
);
}
}
And finally add files/folder ('/web' same as baseUrl) to XCode project
And it works! But I'm not sure how...
Place this script in any file of ReactNative or your code, recomended to first or top index file. And it will fix problem, tested on RN0.39
import { Platform } from 'react-native';
import { setCustomSourceTransformer } from 'react-native/Libraries/Image/resolveAssetSource';
setCustomSourceTransformer(function (resolver) {
if (Platform.OS === 'android'
&& !resolver.serverUrl
&& !resolver.bundlePath
&& resolver.asset.type === 'html') {
resolver.bundlePath = '/android_asset/';
}
return resolver.defaultAsset();
});
You may have to wrap your own Native Module to do this. React Native's WebView uses UIWebView
, for info on loading a local file take a look here: https://gist.github.com/amster/9160860
However it is recommended you use WKWebView
, you can wrap one yourself relatively easily. There is currently a repo that is WIP: https://github.com/qrush/react-native-wkwebview
Accomplishing loading local resources using WKWebView
can be found in this answer: https://stackoverflow.com/a/28676439/398136
I stumbled upon the same issue and, after running in circles for hours trying all sorts of solutions, I finally solved it by following this tutorial. Major kudos to the author.
In the article there's some extra info which is a bit outdated, so here's the concise version instead:
/html
);Web
, with index.html
being your WebView entrypoint), give it a .bundle
extension (e.g. Web.bundle
), and place it into /html
;Now you have to add these files to the project so they are recognized and bundled together in your next build, this process is done differently in iOS and Android:
Web.bundle
into the project's main folder, and confirm the dialog with the "Copy items if needed" option left unchecked;/android/app/build.gradle
and add:android {
...
sourceSets {
main { assets.srcDirs = ['src/main/assets', '../../html'] }
}
}
Now rebuild your project from scratch to have your changes take effect.
In your WebView file, calculate the path to index.html
and feed it to the WebView:
const sourceUri = (Platform.OS === 'android' ? 'file:///android_asset/' : '')
+ 'Web.bundle/index.html';
return (
<WebView
source={{ uri: sourceUri }}
originWhitelist={['*']}
javaScriptEnabled={true}
allowFileAccess={true}
/>
);
This will load your index.html
and all of its js and css files, as long as they're included in the bundle.