Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the Cordova Browser-Sync Plugin not working on a clean, new Apache Cordova app?

NOTE: This issue is reported from multiple parties on the official GitHub repository for Cordova Browser-Sync Plugin as well. Posting this here to bring more attention to the issue and to see if someone has any insight or a practical solution to this.


I’m new to the world of Apache Cordova, but fluent in full-stack LAMP development. That said, I am baffled by this issue: When I create a basic/simple Apache Cordova test application and add Cordova Browser-Sync Plugin to the mix, I can make changes in my www/ directory and then see them immediately reflected in platforms/browser/www/ but my open browser window does not live reload. I have to force a reload to get the changes to be reflected in the browser.

I am running this all on Mac OS X 10.10.5 (Yosemite), NodeJS is 4.4.0, NPM is 2.14.20, Cordova is 6.0.0 and the Cordova Browser-Sync Plugin is 0.1.1.

My steps to set things up are as follows; first create a new app like this:

cordova create MyApp

Then I go into the directory like this:

cd MyApp

And setup my simple “browser” Cordova app like this:

cordova platform add browser

A final test is to just run the app like this:

cordova run browser

Okay, so we know that simple “Hello world.” test works. Now I’ll add the Cordova Browser-Sync Plugin like this:

cordova plugin add cordova-plugin-browsersync

All good and now I will test the application like this:

cordova run browser -- --live-reload

And if I make a change in a file, the browser simply does not “live reload” as described; unless I am missing something? The output from that command is:

Running command: /Users/jakegould/Desktop/MyApp/platforms/browser/cordova/run --live-reload
Static file server running on port 8000 (i.e. http://localhost:8000)
CTRL + C to shut down
Static file server running @ http://localhost:8000/index.html
CTRL + C to shut down
Executing command: open -n -a "Google Chrome" --args --user-data-dir=/tmp/temp_chrome_user_data_dir_for_cordova http://localhost:8000/index.html
[BS] Access URLs:
 --------------------------------------
       Local: http://localhost:3000
    External: http://192.168.1.20:3000
 --------------------------------------
          UI: http://localhost:3001
 UI External: http://192.168.1.20:3001
 --------------------------------------
[BS] Serving files from: platforms/android/assets/www
[BS] Serving files from: platforms/ios/www
[BS] Watching files...
gzip
200 /index.html (/Users/jakegould/Desktop/MyApp/platforms/browser/www/index.html)
gzip
200 /css/index.css (/Users/jakegould/Desktop/MyApp/platforms/browser/www/css/index.css)
gzip
200 /cordova.js (/Users/jakegould/Desktop/MyApp/platforms/browser/www/cordova.js)
gzip
200 /img/logo.png (/Users/jakegould/Desktop/MyApp/platforms/browser/www/img/logo.png)
gzip
200 /js/index.js (/Users/jakegould/Desktop/MyApp/platforms/browser/www/js/index.js)
gzip
200 /cordova_plugins.js (/Users/jakegould/Desktop/MyApp/platforms/browser/www/cordova_plugins.js)
[BS] Reloading Browsers...

Note how it says “Reloading Browsers...” at the end of the list? I assure you 100% not one browser was reloaded. And here is the HTML www/index.html from the root of the application I am attempting to edit to trigger a live reload:

<!DOCTYPE html>
<!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
-->
<html>
    <head>
        <!--
        Customize this policy to fit your own app's needs. For more guidance, see:
            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
        Some notes:
            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
                * Enable inline JS: add 'unsafe-inline' to default-src
        -->
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Hello World</title>
    </head>
    <body>
        <div class="app">
            <h1>Apache Cordova</h1>
            <div id="deviceready" class="blink">
                <p class="event listening">Connecting to Device</p>
                <p class="event received">Device is Fucking Ready</p>
            </div>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

I understand that live reload functionality often relies on inline JavaScript code that is somehow injected into the DOM of the HTML to communicate with the live reload server. And everything I have read online says these kind of issues—where live reload fails—often comes from the <body></body> tags not being set on a page. But they clearly are there. I almost want to think it’s a Content-Security-Policy related issue, but that would only really be a factor if the JavaScript was injected into the page to begin with.

So why exactly is live reload functionality not working in an incredibly bare-bones initial setup like this?

like image 928
Giacomo1968 Avatar asked Mar 13 '16 19:03

Giacomo1968


2 Answers

Code-wise, there doesn’t seem like there is a solution/fix that works. Why? Who knows. But the plug-in as it stands now is broken.

And past the technical specifics, according to this issue ticket on the GitHub repository connected to the official plug-in—and coming directly from the developer of the project itself—the project is “retired.”

I am planning to retire this project in favor of Taco-livereload. That is also based on pretty much the same code, and I am now a PM on that project. That project will also have more devs working on it, so will have much more support as an official project.

Would that fulfill your needs ? Are there anything that this project has, that taco-livereload does not have ?

Since Taco is a Microsoft project, I’m not going to touch that with a 10 foot pole even if they are using an MIT license. Microsoft’s philosophy of “embrace, extend, and extinguish” seems too risky for an open source endeavor like this.

So instead, I’m going to veer towards Ionic as a framework since it has live reload functionality right out of the box and is more widely adopted and embraced by the Cordova development world right now.

PS: The Content-Security-Policy solution discussed on the plug-in author’s blog which suggests setting ws: 'unsafe-inline' would only be a factor if the live reload JavaScript code was properly being injected in the page to begin with. JavaScript from a non-trusted source is what would make the process fail in cases where the plug-in would actually work. And the proof would be seeing such an error in the web browser console after the page loads.

But in this case, the code injection is not happening anymore and starting the application with cordova run browser -- --live-reload starts up the default development server on localhost:8000 but then afterwards the browser sync servers are started for localhost:3000 and localhost:3001. If this setup were working correctly it would be only running on localhost:3000; and not ports 8000 and 3000.

like image 197
Giacomo1968 Avatar answered Oct 13 '22 16:10

Giacomo1968


I think you miss ws: 'unsafe-inline' in your Content-Security-Policy definition.

The plugin needs this CSP for websocket to work.

Have a look to the video there http://blog.nparashuram.com/2015/08/using-browser-sync-with-cordova.html (linked in the plugin's readme.md) for detailed explanations about the plugin usage.

Should be:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: ws: 'unsafe-inline' https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
like image 41
QuickFix Avatar answered Oct 13 '22 15:10

QuickFix