Wednesday, March 23, 2016

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

Leave a Comment

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?

2 Answers

Answers 1

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.

Answers 2

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 *"> 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment