nwjs / nw.js

Call all Node.js modules directly from DOM/WebWorker and enable a new way of writing applications with all Web technologies.
https://nwjs.io
MIT License
40.24k stars 3.88k forks source link

Startup Image / Animation support would be nice #151

Open kaystrobach opened 11 years ago

kaystrobach commented 11 years ago

Hello Guys,

as loading a packaged app takes some seconds, i would like to see a simple startup image during loading (e.g. a png or something similar).

Is there a way to achieve that?

I would have expected it as setting in the package.json file ;)

Regards Kay

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

NRABrasil commented 11 years ago

I want this too!

pmaroncelli commented 11 years ago

That would be a nice to have feature.

pauliusuza commented 11 years ago

I think you can easily achieve this right now using two application windows: the first windows to load is chrome-less and contains only a splash image and an asynchronous loader for your assets and main application code for the second window.

You show the main application window when all assets are loaded and DOM of the main application window is ready.

Will try this later today.

kaystrobach commented 11 years ago

mhmm, not exactly what i want ;)

I mean sth. like this:

  1. click build app.exe (or move zip on nw.exe).
  2. unpack package.json get image
  3. unpack show image
  4. unpack all
  5. launch app, now i can show the window you suggested ;)
  6. lauch main app

The timeframe between step 1 and 3 should be less than a half second. The timeframe between 1 and 5 / 6 can be a minute or more with big applications zip files ;) .

pauliusuza commented 11 years ago

yes, if unpack is causing the delay it makes sense. In my case it's the js pre-processing that's causing majority of the delay

kaystrobach commented 11 years ago

super, is there any chance to get this implemented?

zcbenz commented 11 years ago

I'll implement it in v0.3.4.

kaystrobach commented 11 years ago

thanks in advance :D

rogerwang commented 11 years ago

this is now likely to slip to the next version

gavrochelegnou commented 11 years ago

any chance to see this splashscreen stuff soon ? Thanks a lot !

sindresorhus commented 11 years ago

Agh, please don't add this... Splash screens is a huge annoyance to users. OSes already have built-in ways to show when an app is loading, eg OS X with bouncing dock icon.

kaystrobach commented 11 years ago

not all os show that fast and reliant.

the splash was never intended as a must, but is really sensefull as first reaction during loading a big application. One Application of mine has about 20MB of JavaScript + Images and other stuff, so the startup takes a while and a splash was requested by the user ;D

sindresorhus commented 11 years ago

splash was requested by the user

There could be one vocal user that wants it and thousands that don't.

kaystrobach commented 11 years ago

You simply do not catch the point!

The feature I request is to have a startup screen, if the developer want's it! I do not want any enforcement to have a splash screen. I also never asked to force developers to implement a splash screen!

So please stop complaining, do not use this feature and there should be no noticeable change for you! The discussion is senseless! - This is the last answer you get from me!

sindresorhus commented 11 years ago

I'm just giving you a users perspective on it. I have no say in what gets implemented or not. I just feel there are more important features that could be added than those which will degrade the user experience when used.

kaystrobach commented 11 years ago

ok, than sorry.

i had up to 30 secs of loading time, and my users asked me if the application dies during startup, as windows does not show any good indicator, which states, that the application is still loading :dancer:

So from my perspective the splash screen is an improvement for the usability.

I also agree to your opinion, for the case, that the application can technically start instantly. If possible loading should be as fast as possible, but the user should also get an idea on how long loading will take.

iondisc commented 11 years ago

Has any progress been made on this option? I too have an app that takes some time to load and my client would like some indication that something is happening so their users don't just keep clicking till something happens.

ShivaanKeldon commented 11 years ago

I vote for that too. A stratup image would be great for my game "launch time" ^^

bendi commented 11 years ago

I have the same problem - my zipped app has smth around 10MB and until it's unzipped nothing happens, no indicator is shown under windows, so a splash screen or anything to show user that application is starting would be nice.

katanacrimson commented 11 years ago

-1 - if the user is concerned if the application is starting, they can check a task manager, ps aux, or any number of process listings.

iondisc commented 11 years ago

Damianb, do you really think most "average" users know of such things, or have the patience?

katanacrimson commented 11 years ago

Many are patient enough for applications to load, yes. Please stop with the passive-aggressive behavior.

iondisc commented 11 years ago

My apologies if I came across "passive-aggresive" damianb, I was genuinely curious if you believed in what you had suggested. Personally I disagree with you, but that's my opinion as I don't currently have data at hand to support it so let's not argue over it.

I would rather discuss the issue that some of these apps can take a long time to load with NO "apparent" indication that anything is happening. Rather than ignore the user experience and hope they know how to find out if anything is happening, risk losing their attention all together or worse frustrate them, I would like to take action to make their experience better.

I believe we need a solution that provides A) Some indication that the app is loading and B) A splash screen to brand your app.

kevsmt commented 11 years ago

This is actually does not need an argument, this should or have built-in upon building node-webkit. Every Enterprise or how simple it is and it contains lots of unpacking, splash or branding is always an option.

kaystrobach commented 11 years ago

as it should not be a must, i can't see, why someone is fighting this FEATURE. All my customers where is used node-webkit asked for any indicator during the loading of the Application.

YurySolovyov commented 11 years ago

why not just provide some lightweight startup page with loading indicator, and load heavy resorurces async?

kaystrobach commented 11 years ago

take a look here, it's the unpacking, which causes the delay.

https://github.com/rogerwang/node-webkit/issues/151#issuecomment-10157354

gavrochelegnou commented 11 years ago

because :

YurySolovyov commented 11 years ago

ok, got it, i think it could be possible to implement it simmilar to how window icon is done.

also, api for displaying some text over splash image would be also nice, but this is optional.

katanacrimson commented 11 years ago

Alright, let me explain my position here; nobody's considering the consequences of such a change here it appears.


This just needlessly complicates nw startup IMO and adds to the problem of creating an executable which, by the way, means you still have to partially unpack the zip to get the image itself (after unpacking enough to get the manifest file).

Let's assume the feature is implemented, and you have your splash image specified in the manifest file...

So, now you've just modified the program launch significantly and made it even worse for how much it has to do.

  1. run nw executable
  2. unpack app.zip partially
  3. read manifest file (determine splash image)
  4. unpack app.zip partially (again)
  5. read splash image
  6. render splash image
  7. unpack REST of app.zip
  8. launch application

In adding this "feature", you're adding quite a bit more disk I/O events, some processing (depending on how heavy the compression is), and it all has to happen synchronously in order to just display a pretty picture to let the user know it's starting. Before, we just have to accomplish steps 1,7,3, and 8 (in that order); now we've added three more steps and are further burdening ourselves with the unpacking problem anyways! (woo for being disk and CPU bound again)


If you want a splash screen, find or write a chain loader that will handle that and launch nw at the same time; that way, it doesn't hurt everyone's performance. Otherwise, you're creating a major performance hurdle for everyone to run into.

katanacrimson commented 11 years ago

I've also just had a thought about a potential solution to the root problem: startup is slow due to unpacking of the application...which leads to the deeper question, "why unpack at all?"

Ref #814; perhaps use of tarballs would be ideal, since there's no compression at all within a tarball (compression happens afterwards to the tarball). This would reduce the amount of processing, and depending on the unpack/read mechanism, may reduce disk I/O.

gavrochelegnou commented 11 years ago

Thanks @damianb for this interesting insight.

A few leads that may not slow down everyone :

  1. Generic startup image
    • A generic and small "Loading" screen/indicator shown by nw while unpacking. I think that would already make many people here quite happy to have "any" visual feedbak :)
    • Could be changed by people willing to recompile nw for their needs.
    • Could be using application "icon" (found in exe for windows, info.plist on osx ...)
    • Could be enhanced with percentage if possible ...
  2. An external Image file shipped "outside" the "zip"
    • This doesn't work if you provide the .nw file alone, but i think most people provide "full package" including nw and zip (otherwise fallback to 1. ?)
    • Can be a staticly named file like "splash.png/svg/whatever" and stored :
      • At the root of the .app folder for osx
      • alongside with the exe and dlls for windows
      • alongside with the pak/so/nw on linux
kaystrobach commented 11 years ago

yeah, with convention over configuration this should be easy and fast to solve. As far as i know it's also possible to test if a zip contains a file without unpacking. So if a startup image exist (either in the zip or beside) show it, if not do it as it's done now. (for me, it's not important to configure the image in a textfile, a convention would solve my problem as well).

katanacrimson commented 11 years ago

@kaystrobach that still leaves at least five different fs checks within the zip - (png|svg|gif|jpeg|jpg) - could drop gif but that's still more work within the zip file and it's a tripping point since you're adding a "magic" behavior based on filename.

kaystrobach commented 11 years ago

not true, you can IMHO simply define a convention e.g. startupAnimation.png. Many systems rely on conventions, so why making things complicated? Showing just png's is also a way faster than loading an svg parser or similar stuff.

ironic I mean we could also provide a mp4 file, which is played in sync with the progress of loading the app (10% unpacked, forward to 10% of the movie playback, and so on) ... this way anyone may create custom startup animations. /ironic

katanacrimson commented 11 years ago

@kaystrobach I'm just trying to be objective and help work towards a better solution to the problem at hand; there's no need to get rude.

kaystrobach commented 11 years ago

i don't wanted to be rude!

I saw very good implementations of the mp4 startup animation stuff, so it's not an unrealistic solution. An mp4 is just a bunch of keyframes and differential images which can be used to solve many problems :D. But in case of this discussion this is not rude anyway.

What i can't understand is, we talk about a checks of existance of a file in an archive.

As far as i know, this is easily and extremly fast possible with most zip implementations as ZIP has a directory index. Even on the commandline this is possible. 7-Zip uses this to let you browse the archive without extracting it, as well as other tools.

unzip -l archive.zip

http://superuser.com/questions/462788/read-the-contents-of-a-zipped-file-without-extraction

In numbers: Unzipping a TYPO3 6.1.0 source Zip (http://prdownloads.sourceforge.net/typo3/typo3_src%2Bdummy-6.1.1.zip?download) takes 10 secs. Using the above command takes below 0.01secs outputted to a tty (can't measure more precise without building a real programm)

So it's not a real additional IO operation, but during the opening of the Archive you iterate over the index and look if there is a match in the filenames - this should be pretty fast, and should not add a noticeable drop in performance, as it's just a string comparision.

katanacrimson commented 11 years ago

Using the above command takes below 0.01secs outputted to a tty (can't measure more precise without building a real programm)

Tip - Install appropriate package to get the "time" command, use that for measurements instead (iirc debian uses time for package name? arch has it under time from what I see, and bash has a potentially less reliable builtin, and so does zsh)

e.g.

:katana@solanine ~/
$ time sleep 2
sleep 2  0.00s user 0.00s system 0% cpu 2.015 total

ed: ooh, I was using zsh's time function. /usr/bin/time seems to be a bit different.

:katana@solanine ~/
$ /usr/bin/time -v sleep 2
        Command being timed: "sleep 2"
        User time (seconds): 0.00
        System time (seconds): 0.00
        Percent of CPU this job got: 0%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.00
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 648
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 206
        Voluntary context switches: 2
        Involuntary context switches: 0
        Swaps: 0
        File system inputs: 0
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0

I really do wonder though why the compression here. It seems the primary need is for an archive; hopefully tarballs can be looked at instead and just rid us of decompression entirely.

gavrochelegnou commented 11 years ago

I really do wonder though why the compression here. It seems the primary need is for an archive; hopefully tarballs can be looked at instead and just rid us of decompression entirely.

Then you will have a package that is slower for everyone to download, just to provide a startup image ...

I think compression could really matters on some projects and it would be a bad idea to remove it to gain this functionality. (for example i had to store both osx/windows versions of my project on a DVD and size mattered, download/storage size could matter too ...)

katanacrimson commented 11 years ago

Then you will have a package that is slower for everyone to download, just to provide a startup image ...

Pack the entire installer, unpack on initial installation? Having the user decompress a zip initially is nowhere near as bad, and most can figure out how to extract it out to run it tbh. And for the windows users that don't, there's 7zip self-extracting archives.

YurySolovyov commented 11 years ago

I dont know if it's doable or worth it, but maybe it is possible to extract contents into memory? For projects with heavy resources you still need to unpack, but but for those with <50MB size it coud speed up things.

Maybe it is out of topic, but IMO extracting contents in temporary folder is somewhat uncool,,, we already can protect our JS with v8 snapshot, but what about rest things? is it possible to create some kind of container in the memory so nw can refer to resources there?

Mithgol commented 11 years ago

@damianb

Let's assume the feature is implemented, and you have your splash image specified in the manifest file...

So, now you've just modified the program launch significantly and made it even worse for how much it has to do.

  1. run nw executable
  2. unpack app.zip partially
  3. read manifest file (determine splash image)
  4. unpack app.zip partially (again)
  5. read splash image
  6. render splash image
  7. unpack REST of app.zip
  8. launch application

In adding this “feature”, you're adding quite a bit more disk I/O events, some processing (depending on how heavy the compression is), and it all has to happen synchronously in order to just display a pretty picture to let the user know it's starting. Before, we just have to accomplish steps 1,7,3, and 8 (in that order); now we've added three more steps and are further burdening ourselves with the unpacking problem anyways! (woo for being disk and CPU bound again)

The current state is not quite 1, 7, 3, 8. The app.zip is unpacked entirely, and thus it's more like 1, (2+7), 3, 8.

The suggested behaviour adds steps 4, 5, 6 (unpacking and reading and rendering of the splash) and separates steps 2 and 7 (the manifest is unpacked and read before anything else).

The steps 4, 5, 6 are going to introduce some I/O and CPU burden indeed. The idea behind this suggestion is to pay this price (willingly) for an improvement of the user's perception.

Perceived speed is more important than actual speed, and the user is much happier when something starts happening instantly. The existing delay before an actual application start is prolonged slightly, but the user is entertained through the whole delay.

The suggestion is given under an assumption that user's “look, there's a splash!” experience lasts longer than steps 4 and 5 and 6 combined, and thus the benefit is worth its price.

The suggested practice can also be easily made optional (when the manifest does not mention a splash, the 4+5+6 steps are not happening).

Mithgol commented 11 years ago

Then you will have a package that is slower for everyone to download, just to provide a startup image...

Pack the entire installer, unpack on initial installation? Having the user decompress a zip initially is nowhere near as bad, and most can figure out how to extract it out to run it tbh. And for the windows users that don't, there's 7zip self-extracting archives.

If you pack the installer and unpack on the initial installation, why use any archives at all.

Let the installer make a directory and populate it with unpacked files, and use nw foldername (most likely, nw .) to run your application.

That would prevent the need of any unpacking at application start time.

trevorlinton commented 11 years ago

Hi all,

I've finished an implementation of a new distribution method I think will fill this need quite well. Instead of having to unzip all of the resources on boot each time this stores all distributed files as internal resources and creates a cache look up table (on demand).

It reduces the node-webkit bootime with 200MB of resources from ~33 seconds on a 1.8ghz processor to ~1.2 seconds. It also doesn't break existing implementations/distribution methods.

Downside is it would most likely need to have someone create a open source build system. (It's essentially a magic key + file name + file size + data concatenated and appended to either Content/Resources/Package in MacOSX or the end of the executable on Windows).

Hope it helps.

https://github.com/trevorlinton/node-webkit/commit/3c162a80ae92db5a91f3baee70b97a790dd43eef

trevorlinton commented 11 years ago

I should also mention with this method all content/resources are unpacked in memory and never written to disk.

YurySolovyov commented 11 years ago

wow, amazing! what about debugging? are all resources source files visible in dev tools? anyway i hope it will be merged

trevorlinton commented 11 years ago

@Dream707, yes. Instead of using the default file:// (which uses the old methods) you just switch your protocol prefix in the package to embed://. This tells node-webkit to look back inside of its own resources and returns back the file pointer of the resource (and length) to chromium. This keeps the files from ever being written to disk or requiring them to be unpacked on boot. It also uses chromium caching so the files need to be read from the resources only once.

Preventing disk IO significantly improves speed, in addition the files can be gzipped or left unpacked depending on your preference. This also helps protect code (it just makes it a little more difficult for people to crack) rather than current methods of unpacking the zip file to a temporary directory.

Debugging/dev tools still work perfectly find, it just shows that the html/js/whatever file is from embed://YourFile.html rather than file:///YourFile.html

I passed it on to Roger who said he'd take a look. If anyone is willing to make a shell script for all platforms to create bundles using this method that would be great (I'm really pressed for time right now otherwise I would). The format is in the code I committed but if you have questions let me know.

katanacrimson commented 11 years ago

@trevorlinton What's the memory footprint look like, though? I'm quite curious of the potential impact.

trevorlinton commented 11 years ago

@damianb The files themselves aren't cached in memory (with the exception of chromiums normal caching mechanisms/policies) however the table that points to where the files begin/end within the package are cached and is fairly minimal. (You can calculate the size of the cache table, its 64 bits (file size), file name (at most 256 double bytes for utf8, so 512 max) and the magic key twice which is 14 bytes. So total: (22bytes+512bytes) * number of files in the package.

I ran it on a package (as a test) of 300 pdf's totaling around a gigabyte package and there was no significant change in the memory footprint.

This method is commonly used for large file packages, similar to how grit or windows pe resource tables work.

katanacrimson commented 11 years ago

@trevorlinton Sounds good; are there any other potential downsides that you can think of, other than packaging?