Index Thing

Index

The NW.js Thing


The NW.js Page

Basically this page encapsulates some of the experience I have had with using NW.js

A short history:
NW.js started out as Node-Webkit which basically uses the Chrome/Chromium browser in conjunction with Node.js providing a unified framework for the client/server contexts based on javascript - it allows cross-platform development of desktop applications utilizing web technologies (HTML/CSS/JS). It should be noted that a similar project exists called Electron (formerly Atom) which does seem to be gaining traction with larger companies (eg: Microsoft with Visual Studio Code) and a number of apps formerly built with NW.js have now moved to Electron.
Unfortunately the position between the two may turn out like a VHS/Betamax thing and I hope that NW.js isn't the Betamax ....

Not sure I can remember how I came across this but at the time I was looking for a technology to make apps for the desktop that was also cross-platform. Q7Basic which I was using for a couple of projects had been abandoned and YWE although still useful was no longer supported

Legacy:

Basic/Visual Basic projects
Visual Basic was just getting too cumbersome with .NET frameworks, etc. Tried Q7Basic which was excellent but unfortunately has been abandoned by the sole owner. Q7Basic was built on Qt4 and had some limitations which would need delving into the C++ world of Qt which is a bit much for me. I also found the compilation time needed for projects was getting tiresome. The cross-platform capability was a bit limited.

Konfabulator/Yahoo Widgets Engine projects
This was a great wee app that still generally works on later OSes but has been abandoned by Yahoo for a few years now. I used this for a number of widgets and being based on web technologies it didn't require huge amounts of compilation time.

Now:

NW.js ticks a lot of boxes for me -
Cross-platform (OSX/Win/Linux)
Web technologies (HTML/CSS/JS)
No compilation required
Easy to encapsulate web sites into desktop apps
Transparency to allow widget type functionality

The only major thing NW.js could do with is a Visual Basic standard IDE to assist visual design (I think it is happening but likely to be online only eg: Macaw)

Current State of the Play:
The original Node-Webkit framework was forked (Node.js and io.js) but under NW.js the forks have merged again on Node.js
v0.12.3 was the last stable build before NW.js was re-architected in v0.13, any apps built with 0.12.3 generally need to be adapted to run with 0.13 or later although some 0.12 compatibility has been built into the later releases. Since 0.13 the NW.js builds are released frequently in conjunction with stable builds of Chrome.

On balance for me (a non-professional hobbyist) NW.js offers a great way to build cross-platform desktop apps that work relatively easily but be aware that documentation can be quite sparse in places (Basic tended to be great in this respect). NW.js offers me a good replacement for Visual Basic/Basic (aside from the lack of an IDE).

Documentation can be sparse - the official docs usually give enough for professional developers to use but for the lesser skilled hobbyist it will involve a lot of searching/trawling to understand some stuff. A particular hassle is with plugins/extensions for audio/flash/etc - the docs will say it can be done and give a short one-liner but there is very little by way of example on how to do it.
I have included sections below to try and fill out areas that I have come across which may help some folk.

There are quite a lot of books on Node.js and a few on NW.js in particular however a lot of the existing books/documents/sample projects (as at early 2016) are still based on 0.12.3 or earlier. With the advent of the re-architected 0.13 and later docs can be a bit thin and prior knowledge of the Chrome/Chromium project is assumed.
One book I have found to be excellent is written by Paul Jensen.
It is currently available via the Manning Early Access Program (MEAP) and is titled -
Cross-Platform Desktop Applications with Node, Electron and NW.js HERE



Useful NW.js Links



NW.js site HERE the main site with docs, etc


Live Builds HERE useful for getting latest builds


Web2Executable HERE use for packaging Apps


Node.js site HERE the main Node.js site with docs, etc


NPM site HERE tons of useful modules


Chromium Command Line Switches HERE used with chrome-arguments in package.json


Universal Graphical User Interface project HERE useful for learning



NWjs Concepts/Packaging



Node-Webkit : Uses Node.js and Webkit browser
NW transition : Uses io.js and Chrome browser with Blink rendering engine
NW.js : Uses Node.js and Chrome browser with Blink rendering engine

OS support is quite broad -
   Windows: OK from Windows 7 onwards.
     Vista using the Aero interface will be OK with transparency.
     XP/Vista non-Aero will work but will have problems with transparency since graphics layering is used rather than compositing.

   OSX: Generally OK from 10.6.8 (Snow Leopard).

Since 0.13 the builds tend to favour 64bit OS support and XP support exists upto 0.14.x LTS.

If a NW.js binary is started outside an app folder (therefore no package.json found) the default window will show as -

The NW.js Default Screen

Typical OSX Project to produce a desktop App:



New Project :: - call it Hippo

I generally use two styles of App - normal desktop mode and transparent widget type, Hippo is setup as a widget style App.

Hippo
=> App folder
=> Resources folder (Icons,plist,etc for project)
=> Info.plist file

App folder
=> package.json file (REQUIRED)
=> index.html (or similar REQUIRED for main in package.json)
=> node_modules folder (REQUIRED for NPM modules)
=> css folder
=> js folder
=> Resources folder (images,etc within application)

The NW.js binary can be placed in the App folder and if double-clicked will startup as the application. The binary will look for the package.json (also called the manifest) and execute it - the start page is generally specified as the main: parameter within the manifest.

When the application is run the support files will be placed in User/Library/Application Support/Hippo
Strange issues/problems with the app can sometimes be cured by deleting this folder and it will be recreated next time the app is run.






Using NPM modules ::

NWjs makes use of the NPM packaging system which gives quite a lot of flexibility in projects.

To use fs-extra with project called Hippo eg:
Use Terminal and navigate to Hippo project folder and then to App folder within then enter -

npm install fs-extra --save

This will install the npm module fs-extra into the node_modules folder within the app folder and the save command will write the dependencies into the package.json file of the app folder.

NOTE: NPM modules should be installed/uninstalled correctly to best avoid error issues during development.

Packaging the App ::

My packaging app of choice is Web2Executable which creates cross-platform app packages.

I tend to develop on the OSX platform but Web2Executable allows me to use the same source project to package for Win/Linux as well. It should be noted however that certain OS particular features may be easier to develop on the appropriate platform eg: transparent widgets on Windows will tend to require use of the context menu whereas the OSX native menu can still be used if desired. Windows also makes use of the registry quite a bit.
It is quite OK to use the same source folder arrangement on the Windows platform - the app can be run by simply dragging the app folder (containing package.json) onto the nw.exe binary.

NW Structure - Basic Layout of a Packaged App (OSX) using 0.12.3

NW Structure - Basic Layout of a Packaged App (OSX) using 0.13 or later

Download Hippo project source (ZIP) HERE
 Sample NW.js transparent widget type app called Hippo -
=> Unzip and place NWjs binary into the Hippo folder(contains package.json) - 0.14 or later
=> Double-click NW.js binary to run app

Use Web2Executable to package project if desired.


Using Audio/Video (MP3/MP4)



NW.js is not licensed to distribute the MP3/4 FFMPEG codecs so if an app is to be distributed commercially the developer has to custom build the codecs with the licensed ones.

Pre-built codecs can be obtained from various sources - some work, some don't.

OSX -
libffmpeg.dylib from PersonaTool app - this replaces the provided .dylib in nwjs Framework.framework bundle.
Works OK with 0.13.4, 0.14.2 and 0.15.0

libffmpeg.dylib from Electron app - this replaces the provided .dylib in nwjs Framework.framework bundle.

iteufel also provides some pre-built binaries on GitHub - https://github.com/iteufel/nwjs-ffmpeg-prebuilt/releases


Using Flash



Basically everyone is running away from Adobe Flash as fast as they can but there is still a lot of legacy requirements out there.
Chrome no longer supports NPAPI plugins but now use Pepper Flash plugins (PPAPI). NW.js does not include a flash plugin but it can be obtained from Chrome/Chromium packages.

OSX -
The PepperFlash folder resides in the Internet Plug-Ins folder within the Chrome/Chromium Framework.framework package
This needs to be placed in the nwjs Framework.framework/Internet Plug-Ins folder of the NW.js binary
NOTE: NW.js requires a manifest.json file to accompany the PepperFlashPlayer.plugin and this is NOT provided in the Chrome/Chromium apps so here is an example - HERE - typical for use with PepperFlashPlayer.plugin
- download HERE

Using Webview Tag -

index.html -
<webview id="wbv" src="sound.swf" style="width:200px; height:100px" partition="trusted"></webview>

package.json -

   "webkit": {
      "plugins": true
   },
   "webview": {
      "partitions": [
         {
            "name": "trusted",
            "accessible_resources": [
                  "<all_urls>"
            ]
         }
      ]
   }



Handy manifest (package.json) settings



Transparency ClickThrough requires -
   "resizable": false
   "chromium-args": "--disable-gpu --force-cpu-draw"

Print Preview uses PDF plugin so requires -
   "plugin": true for webkit parameter

Full DevTool logging may require -
   "chromium-args" : "--mixed-context"

Debug logging (chrome_debug.log file in Application Support/<Appname> folder)    "chromium-args": "--enable-logging --v=1"



General



Storage of app specific settings (NWjs) -
~/Library/Application\ Support/<appname>
NOTE: Deleting this folder can sometimes clear unexplained errors and the folder will be re-created the next time the app is run.

Java Applet support ceased about 0.13 since later Chrome browsers no longer support it. Support exists in 0.12.3

PDF support is built in to NW.js


Chrome Extension Support



package.json

"chromium-args" : "--load-extension" eg: "chromium-args" : "--load-extension=/Users/whateveruser/Desktop/fmkadmapgofadopljbjfkapdkoienihi"

Extension can be taken from chrome (unpacked).
chromium-args requires a full path - relative will not work.
eg: using react-devtools example -

"chromium-args" : "--load-extension=/Users/whateveruser/Desktop/fmkadmapgofadopljbjfkapdkoienihi"

"chrome-extension://*" needs to be placed in permissions of manifest.json inside extension folder



Drag and Drop



Still working on this!

HTML -
<div id="dnd">Drag folder<br />HERE</div>

JS -
// prevent default behavior from changing page on dropped file
window.ondragover = function(e) { e.preventDefault(); return false };
// NOTE: ondrop events WILL NOT WORK if you do not "preventDefault" in the ondragover event!!
window.ondrop = function(e) { e.preventDefault(); return false };

var dnd = document.getElementById('dnd');
dnd.ondrop = function(e) {
   var length = e.dataTransfer.items.length;
   for (var i = 0; i < length; i++) {
      var entry = e.dataTransfer.items[i].webkitGetAsEntry();
      console.log("ENTRY "+entry);
      if (entry.isFile) {
      // do whatever you want
   console.log("Seen as File ");
      } else if (entry.isDirectory) {
      // do whatever you want
   console.log("Folder Dropped ");
      }