0

I am trying to load an HTML file from Bundle. This is the code I use,

let fileUrl = Bundle.main.url(forResource: "index", withExtension: "html")!
webView.loadFileURL(fileUrl, allowingReadAccessTo: fileUrl)

If it is a simple HTML file, I see WKWebview is loading them fine. But right now I am trying to load the HTML which is created using React Native. I don't see any problem with React native web code because its loading fine in local.

While checking logs, I just found that it is failing to load *.js file.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover"
    />
    <title>Bundle HTML</title>
 </head>
    <div id="root"></div>
  <script src="/bundles/web-4587a25eab359d254810d3f9017eb281.js"></script>
</html>

Not sure why the this js & other resources not loading fine. Any idea?

I have added the following config for WKWebView as well. allowsContentJavaScript as true and allowFileAccessFromFileURLs as true

Perseus
  • 1,546
  • 4
  • 30
  • 55
  • Is the html file and the js file at the same level in the bundle? If so, then change the `script src` to `"web-4587a25eab359d254810d3f9017eb281.js"`. The `/bundles/` is a problem. – HangarRash May 15 '23 at 19:46
  • THanks @HangarRash. This changes helps me to load my HTML file. But the assets/resources is not loading fine now. Seems like thee same case for them too. But there is no workaround for this ? – Perseus May 16 '23 at 01:04
  • You don't show any example of assets being used in your question so it's difficult to help. Just keep in mind that all of the html/js/images/etc. will be stored together in the app bundle so all `src` attributes need to be direct references with no path. – HangarRash May 16 '23 at 01:20

1 Answers1

0

Pretty straightforward forward, this path resource cannot be found:

  <script src="/bundles/web-4587a25eab359d254810d3f9017eb281.js"></script>

You should manually replace this path with real path inside your app's bundle, so the final code may look like below

// Get the URL for index.html
guard let fileUrl = Bundle.main.url(forResource: "index", withExtension: "html") else {
    fatalError("Failed to load index.html")
}

do {
    // Load the HTML file into a string
    let htmlString = try String(contentsOf: fileUrl)

    // Find and replace the bundle path with a new path inside the main bundle
    let bundlePath = Bundle.main.path(forResource: "web-4587a25eab359d254810d3f9017eb281", ofType: "js")!
    let newHtmlString = htmlString.replacingOccurrences(of: "/bundles/web-4587a25eab359d254810d3f9017eb281.js", with: bundlePath)

    // Load the modified HTML string into the web view
    webView.loadHTMLString(newHtmlString, baseURL: fileUrl)
} catch {
    print("Error loading HTML file: \(error)")
}

Another better approach is using func loadHTMLString(_ string: String, baseURL: URL?), baseURL here means:

The base URL to use when the system resolves relative URLs within the HTML string.

// Load the HTML file into a string
guard let htmlFilePath = Bundle.main.path(forResource: "index", ofType: "html"),
      let htmlString = try? String(contentsOfFile: htmlFilePath)
else { return }
 
//TODO: Set the base URL to the directory containing the `bundles/xxxx.js` folder, or you can set it 
let baseURL = URL(fileURLWithPath: bundleParentPath)
 
// Load the HTML string into a WKWebView
webView.loadHTMLString(htmlString, baseURL: baseURL)
kakaiikaka
  • 3,530
  • 13
  • 19
  • Thank you @kakaiikaka. But I wonder if that is the case for all the assets too? For eg., this is just one file that comes along when exporting React native web. But there are lot of files in assets too, they are not getting loaded too. – Perseus May 16 '23 at 01:02
  • If you are talking about resources inside Assets.xcassets, that's not a easy task, if you ever checked the exported app, it is compressed into a file named "Assets.car", who is no longer a folder. So I encourage you to just place the resources in the main bundle, if you think that is messy, you can put all of them in a new bundle, just like this https://stackoverflow.com/questions/41129204/get-path-of-a-file-in-a-data-set-located-in-assets-xcassets#answer-41129688 – kakaiikaka May 16 '23 at 02:46