Skip to content

WebView: Add an option to load local resource from the app bundle #505

Closed

Description

@pilwon

<WebView/> currently only supports url prop to control what content to load in the web view.

We need an option to load local resource (mainly html but could be others too) from the application bundle.

We could either introduce a new prop for that or reuse url and do some magic conversion. For example, local://<path>.<ext> can be automatically converted to file:///<converted-url>.

NSURL *convertedURL = [[NSBundle mainBundle] URLForResource:@"<path>" withExtension:@"<ext>"];

(Use case: #497)


[UPDATE]

As @nicklockwood mentioned in his comment #505 (comment), this works out of box by simply setting a relative file path to url prop. (ex: index.html)

Activity

  1. AbeEstrada commented on Mar 30, 2015

    @AbeEstrada

    👍

  2. adriansdev commented on Apr 3, 2015

    @adriansdev

    +1

  3. nicklockwood commented on Apr 27, 2015

    @nicklockwood
    Contributor
  4. pilwon commented on Apr 27, 2015

    @pilwon
    ContributorAuthor

    @nicklockwood What kind of string values does html prop expect? Looks like you closed a wrong issue. The above link points at a line modified by the commit 4b4e8ec and it partially fixes #506, not #505. Can we reopen this issue? I am afraid we are not ready to close #506 as well.

  5. nicklockwood commented on Apr 27, 2015

    @nicklockwood
    Contributor

    Oh, sorry, quite right. But as it happens, any relative URL is considered to be relative to the app resource bundle, so <WebView url="foo.html" /> should load a file called foo.html that's been added to the project.

  6. nicklockwood commented on Apr 27, 2015

    @nicklockwood
    Contributor

    Let me know if that isn't working, and I'll re-open.

  7. pilwon commented on Apr 27, 2015

    @pilwon
    ContributorAuthor

    @nicklockwood It works! 🙀🙀🙀 This is the best solution for this issue 🤘 Thanks-

  8. mydearxym commented on May 10, 2015

    @mydearxym

    @nicklockwood i use the method <WebView url="test.html" /> and it show :

    Error setting property 'url' of RCTWebView with tag #507: The file 'test.html -- file:///Users/xieyiming/Library/Developer/CoreSimulator/Devices/283F4434-57…rs/Bundle/Application/72594A59-1805-4D5C-B8AB-AB79958D08B6/phone_side.app/' does not exist

    and i tried html option too , not work either~

  9. carbonphyber commented on Sep 4, 2015

    @carbonphyber

    @mydearxym Local files must also be compiled into the bundle.
    See step #2

  10. gs-akhan commented on Nov 12, 2015

    @gs-akhan

    @carbonphyber @nicklockwood I am unable to load html file using query params
    example "index.html?data=hello"
    :(
    Thanks

  11. nicklockwood commented on Nov 12, 2015

    @nicklockwood
    Contributor

    @gs-akhan Yeah, that won't work - file paths can't have GET params.

  12. DaveAdams88 commented on Feb 3, 2016

    @DaveAdams88
    Contributor

    This works great in iOS, but having trouble getting it to work with android - I've put the web view in "android/app/src/main/assets/" - and using "source='webview.html'" - is there a step I am missing? .. or am I flat out doing it wrong? :s

  13. nicklockwood commented on Feb 3, 2016

    @nicklockwood
    Contributor

    @dmmiller, do relative paths work the same way in Android as they do in iOS? Can you use "foo.html" as a shorthand for "android/app/src/main/assets/foo.html" ?

  14. dmmiller commented on Feb 5, 2016

    @dmmiller

    @nicklockwood Not sure. I'll check it out on Monday

  15. 29 remaining items

  16. kaykaul commented on Mar 30, 2017

    @kaykaul

    How can I load local css file into web view's html?

  17. dijimon commented on Apr 20, 2017

    @dijimon

    Is it correct to use source={{uri: path_to_file}} for iOS app?
    If yes, than what url format should I use. I mean in android I'm using 'file:///android_asset/path_to_file', but what in iOS?

  18. mishuagopian commented on Apr 20, 2017

    @mishuagopian

    @dijimon in iOS you have to link the file to your project as it is specified in this guide, in which the author links fonts.

    Once you've done that, you can do something like the following when rendering the WebView:

     <WebView source={{ uri: Platform.OS === 'ios' ? 'the-linked-file.html' : 'file:///android_asset/path-to/the-linked-file.html'; }} />

    Remember importing Platform and WebView as the following:

    import { Platform, WebView } from 'react-native';
  19. dijimon commented on Apr 20, 2017

    @dijimon

    But if I don't want to do it manually in Xcode. For instance I want to add some files to the app bundle using some script before making a build, and then I want to require one of those files for showing WebView (when the app is working)

  20. mishuagopian commented on Apr 20, 2017

    @mishuagopian

    Maybe you can do the link programatically, but I've never than that 👎

  21. dijimon commented on Apr 20, 2017

    @dijimon

    I guess there is no way to include some file to the WebView on the fly on iOS.
    Because require('path_to_file') doesn't support dynamic urls
    and {uri: 'path_to_file'} requires to add files manually using Xcode

  22. gs-akhan commented on Apr 23, 2017

    @gs-akhan

    @dijimon What is the use case you want to add dynamic files ? May be I can help
    Thanks

  23. shaunsaker commented on Oct 4, 2017

    @shaunsaker

    @Dryymoon Too legit, thank you!

  24. dayongxie commented on Nov 15, 2017

    @dayongxie

    I found the function getDevServerURL and getBundleSourceURL from resolveAssetSource.js, It's helpfull.
    And I create my workaround solution , it worked in both dev and production mode

    function getBundleSourceURL(): ?string {
        if (_bundleSourceURL === undefined) {
            const scriptURL = NativeModules.SourceCode.scriptURL;
            if (!scriptURL) {
                // scriptURL is falsy, we have nothing to go on here
                _bundleSourceURL = null;
                return _bundleSourceURL;
            }
    
            let match = scriptURL && scriptURL.match(/^https?:\/\/.*?\//);
            if (match) {
                // Bundle was loaded from network
                _bundleSourceURL = match[0];
                return _bundleSourceURL;
            }
    
            _bundleSourceURL = scriptURL.substring(0, scriptURL.lastIndexOf('/') + 1);
    
            if (scriptURL.startsWith('assets://')) {
            // android: running from within assets, no offline path to use
               _bundleSourceURL = _bundleSourceURL.replace('assets://', "file:///android_asset/");
               return _bundleSourceURL;
            }
            if (!scriptURL.startsWith('file://')) {
                // Add file protocol in case we have an absolute file path and not a URL.
                // This shouldn't really be necessary. scriptURL should be a URL.
                _bundleSourceURL = 'file://' + _bundleSourceURL;
            }
        }
    
        return _bundleSourceURL;
    }
    
    export default class WebPage extends Component<{}> {
        static navigationOptions = ({navigation})=> {
            return {
                title: `${navigation.state.params.title}`,
            }
        };
    
        render() {
            let {source} = this.props.navigation.state.params;
    
            if (typeof(source) === 'string') {
                if (!source.match(/^.*:\/\/.*?/)) {
                    if (getBundleSourceURL()) {
                        source = getBundleSourceURL() + source;
                    }
                }
                source = {uri: source};
            }
            return (
                <View style={{flex:1}}>
                    <WebView
                        source={source}
                    />
                </View>
            );
        }
    }
  25. vvavepacket commented on Jan 2, 2018

    @vvavepacket

    what is the equivalent android/app/src/main/assets for iOS?

  26. sujitpk-perennial commented on Feb 12, 2018

    @sujitpk-perennial

    @vvavepacket need to create main.jsbundle. Check this #4084

  27. arash-hacker commented on Apr 24, 2018

    @arash-hacker

    hey guys
    found the trick base on Image doesn't show after bundling into the apk.
    as you know require('index.html') work on simulator and emulator for both &driod and IOS
    but problem will faced when you bundle and you want release your app
    for android just follow this enablejavascript and copy you files in assets folder in YOUR_APP/app/src/main/assets and use just picture below.

    and for ios just bundle package with
    react-native bundle --entry-file index.ios.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios
    when bundle created you have main.bundle.js and asset folder
    just copy you files in .xcworkspace like this image
    ios
    and set free all refrence in will be and unchanged just like mine.
    screen shot - - at
    i hope this tutorial help you from confusing release app in RN

  28. arash-hacker commented on Apr 24, 2018

    @arash-hacker

    worked with rn 0.54 🙏

  29. locked as resolved and limited conversation to collaborators on May 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions