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 is gaining a lot of traction with devs/larger companies (eg: Microsoft with Visual Studio Code).
Unfortunately I notice a number of apps formerly built with NW.js have now moved to Electron and the resourcing of Electron looks more plentiful - looking a bit like a VHS/Betamax scenario however I'm happy enough with NW.js although I find understanding the contexts a bit tricky but I don't want to have to work out how Electron does stuff ....

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

Current State of the Play:
NW.js has been updated quite regularly (inline with the Chromium browser) since the architectural change from Node-Webkit 0.12.3 to NW.js 0.13 and currently 0.32 works pretty well.

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 - I think it is happening but likely to be online only eg: Macaw).

Documentation has improved a bit but the wiki that exists still adds confusion - it was done for 0.12 and earlier and only some parts are good for the 0.13 or later versions. Unfortunately a lot of forum references still relate to the old wiki which can be confusing.
The official docs usually give enough for professional developers to use but for the lesser skilled hobbyist needing real world examples 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

Bug Support:
The team available to fix bugs with NW.js is extremely small (King Roger Wang and a couple of others) but important bugs are usually dealt with promptly. I find it helps a lot by providing a wee sample app that demonstrates the problem and therefore 'puts it on a plate' for the developer - quick turnaround may ensue. P1 bugs are generally quick (crash bugs are generally P1), P2 less so but a sample helps.



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 (NOTE: this repo is now unmaintained)


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 Courtesy The Jared Wilcurt - useful for learning


Gitter site HERE Good forum superbly held together by The Jared Wilcurt


NW.js site HERE the official NW.js mailing list


StackOverflow HERE search for nwjs


Chromium site HERE Chromium download site (NW.js is based on Chromium code base)



NWjs Concepts/Packaging



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

OSX support is 64bit only with the later releases of NW.js - 0.29.0 or later supports OSX 10.10 onwards.
Windows: OK from Windows 7 onwards (32/64bit).
Legacy Windows: Vista using the Aero interface will be OK with transparency (not supported with later NW.js).
 XP/Vista non-Aero will work but will have problems with transparency since graphics layering is used rather than compositing (not supported with later NW.js).
Linux: There is 32/64bit support but may need particular versions of distros.

NW.js 0.14.x LTS supports XP.

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 now a custom version of nw-builder with a GUI frontend which creates cross-platform app packages.

I tend to develop on the OSX platform but nw-builder 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 (legacy)

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 a builder app to package project if desired.


Using Audio/Video (MP3/MP4)



Since c. 0.22.1 NW.js has included the MP3 codecs (patent restrictions just expired). Pre-built codecs can be obtained from various sources - some work, some don't.

The iteufel GitHub repo is the best source for pre-built binaries - https://github.com/iteufel/nwjs-ffmpeg-prebuilt/releases

OSX - libffmpeg.dylib
Win - ffmpeg.dll
Linux - libffmpeg.so

NWjs includes -
  theora
  vorbis
  vp8 & vp9
  pcm_u8, pcm_s16le, pcm_s24le, pcm_f32le, pcm_s16be & pcm_s24be
  mp3 (v0.22.1+)

iTeufel pre-built adds -
  aac
  h264

I guess that the status of codecs should be checked if apps are destined fro commercial distribution however.


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 Adobe.

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>"
            ]
         }
      ]
   }

Current status as at 0.32.0:
If PepperFlash is installed within the app and on the system NW.js seems to use the latest version available.
   eg: (checked on OSX)
         App Version       System Version
         30.0.0.113            27.0.0.183  -->  App version used
         27.0.0.183            30.0.0.113  -->  System version used
             N/A                 27.0.0.183  -->  System version used
         30.0.0.113                  N/A      -->  App version used

The PPAPI version of flash is available from Adobe for all OS types.


Handy manifest (package.json) settings



Transparency ClickThrough requires -
   "frame": false
   "resizable": false
   "chromium-args": "--disable-gpu --force-cpu-draw" (pre - 0.28)
   "chromium-args": "--disable-gpu-compositing --force-cpu-draw" (since 0.28)

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 ");
      }



Project Building



The toolchain for NW.js is rather fragmented - project build/update tools tend to get left to the community rather than be integral to the NW.js project (shows lack of support from bigger companies/stronger developer base).

Build tools:
   nw-builder -> npm package available - CLI app using js - github repo limping along not very active.
   nwjs-builder-phoenix -> npm package available - CLI app using js - supercedes nwjs-builder - github repo more active.
   web2executable -> GUI app using Python - github repo no longer maintained

I was using web2executable which worked fairly well but since maintenance has ceased I have migrated to a custom build of nw-builder which underpins a homemade GUI.
HERE - WIP
HERE - WIP

Most builders will output a folder with executable files but further packaging (eg: DMG, MSI, EnigmaVB, etc) will require further tools. Many developers will choose CLI tools such as Grunt, Gulp, Yeoman, etc

Update Tools:
   Again Update tools are generally not available with the project and rely on the community to some extent (Electron is well supported in the updating stakes eg: Squirrel).

Signing Tools:
   I don't personally develop for the Mac App Store but tried to incorporate it in my builder GUI however documentation regarding signing is sparse and as a hobbyist I haven't paid the required yearly Developer's Signing Fee from Apple which is a required pre-requisite. The only MAS build for NW.js is using 0.19 (current build - 0.32) and it appears to be a resourcing issue to produce a later version.
It is difficult to differentiate between signing procedures for apps destined for the MAS and those that are distributed via normal download methods. I believe an app can be signed without using the MAS build but again the process is unclear and good examples lacking. It definitely looks like the OSX Gatekeeper will only let an app auto run if a correct signature is found (this means a yearly Developer fee folks).
The GateKeeper blocking is becoming a hassle because the option to allow unsigned apps in Sys Prefs has been removed in High Sierra (identified developers only) and unsigned apps will have to be manually authorised by the user on the first run.

Content Verification is also thrown into the mix and this works with caveats.
This basically provides a couple of files (verified_contents.json/computed_hashes.json) within the app that are used by NW.js to determine if content files have been altered. I can get it to work but due to outstanding bugs (#6540/#6541) implementation can't be done using just the latest build.


Important Changes




Architectural changes (major) - 0.13.0

Last XP supported build - 0.14.7

CSS Grid supported - 0.21.0

Architectural change (symlinks used in nwjs Framework.framework bundle) - 0.22.0

MP3 codec included - 0.22.1 (patents expired)

Headless Chromium supported - 0.23.0

Helper Renaming supported - 0.24.4 - uses product_string parameter in package.json (if running an app using the standard nwjs binary this needs to be set as 'nwjs' otherwise should be the app name when packaged).

Architectural change (libffmpeg location moved up to parent folder) - 0.25.0

fs.copyFile/copyFileSync supported - 0.25.2 (node 8.5.0)

Min OSX 10.9 required - 0.26.0

Widevine supported - 0.29.0

Min OSX 10.10 required - 0.29.0



Application Package Renaming




eg: App name is foobar

package.json --> new parameter --v
      product_string: foobar

Contents/Info.plist - CFBundleDisplayName --> update to foobar
Contents/Resources/en.lproj/InfoPlist.strings - CFBundleDisplayName --> update to foobar
Contents/Versions/n.n.n.n/nwjs Helper.app/Contents/MacOS/nwjs Helper --> rename to 'foobar Helper'
Contents/Versions/n.n.n.n/nwjs Helper.app/Contents/Info.plist --v
      - CFBundleDisplayName --> update to foobar
      - CFBundleExecutable --> update to foobar (avoid broken icon on Helper package)
      - CFBundleName --> update to foobar
Contents/Versions/n.n.n.n/nwjs Helper.app --> rename to 'foobar Helper.app'



Widevine Support




Sourcing -

OSX - included in NWjs but is in libraries folder in versions branch
Win32 - Chrome Downloads - install and see below
Win64 - Chrome Downloads - install and see below
Linux32 - Chrome Downloads - unavailable
Linux64 - Chrome Downloads - google-chrome-stable_current_amd64.deb - unzip and drill data.tar.xz folder - data/opt/google/chrome/

- OSX:

      Contents/Versions/66.0.3359.117/nwjs Framework.framework/Libraries/WidevineCDM/ (nwjs.app package)

- On a 64-bit #windows:

      C:\Program Files (x86)/Google/Chrome/Application/66.0.3359.117/WidevineCDM/

- On a 32-bit #windows:

      C:\Program Files/Google/Chrome/Application/66.0.3359.117/WidevineCDM/