Select Page
Browse Files and Folders with Node.js

Browse Files and Folders with Node.js

Watching a file or directory for changes is an important part of automation.  We all enjoy using our favorite CSS preprocessor’s “watch” feature — we can still refresh the page and see our changes as though we were simply writing in pure CSS.  Node.js makes both file and directory watching easy — but it’s a bit more difficult than you may think.

Simply put:  Node.js’ watching features aren’t consistent or performant yet, which thedocumentation admits.  The good news:  a utility called chokidar stabilizes file watching and provides added insight into what has happened.  chokidar provides a wealth of listeners;  instead of providing boring reduced examples, here’s what chokidar provides you:

var chokidar = require('chokidar');

var watcher = chokidar.watch('file, dir, or glob', {
  ignored: /[\/\\]\./, persistent: true
});

var log = console.log.bind(console);

watcher
  .on('add', function(path) { log('File', path, 'has been added'); })
  .on('addDir', function(path) { log('Directory', path, 'has been added'); })
  .on('change', function(path) { log('File', path, 'has been changed'); })
  .on('unlink', function(path) { log('File', path, 'has been removed'); })
  .on('unlinkDir', function(path) { log('Directory', path, 'has been removed'); })
  .on('error', function(error) { log('Error happened', error); })
  .on('ready', function() { log('Initial scan complete. Ready for changes.'); })
  .on('raw', function(event, path, details) { log('Raw event info:', event, path, details); })

// 'add', 'addDir' and 'change' events also receive stat() results as second
// argument when available: http://nodejs.org/api/fs.html#fs_class_fs_stats
watcher.on('change', function(path, stats) {
  if (stats) console.log('File', path, 'changed size to', stats.size);
});

// Watch new files.
watcher.add('new-file');
watcher.add(['new-file-2', 'new-file-3', '**/other-file*']);

// Un-watch some files.
watcher.unwatch('new-file*');

// Only needed if watching is `persistent: true`.
watcher.close();

// One-liner
require('chokidar').watch('.', {ignored: /[\/\\]\./}).on('all', function(event, path) {
  console.log(event, path);
});

What a wealth of handles, especially when you’ve experienced the perils of `fs` watch functionality.  File watching is essential to seamless development and chokidar makes life easy!

Building Your First Desktop App With HTML,Node-WebKit and JS

Building Your First Desktop App With HTML,Node-WebKit and JS

These days you can do pretty much anything with JavaScript and HTML. Thanks to Node-WebKit, we can even create desktop applications that feel native, and have full access to every part of the operating system. In this short tutorial, we will show you how to create a simple desktop application using Node-WebKit, which combines jQuery and a few Node.js modules.

Node-WebKit is a combination of Node.js and an embedded WebKit browser. The JavaScript code that you write is executed in a special environment and has access to both standard browser APIs and Node.js. Sounds interesting? Keep reading!

Installing Node-WebKit

For developing applications, you will need to download the node-webkit executable, and call it from your terminal when you want to run your code. (Later you can package everything in a single program so your users can only click an icon to start it).

Head over to the project page and download the executable that is built for your operating system. Extract the archive somewhere on your computer. To start it, you need to do this in your terminal:

# If you are on linux/osx

/path/to/node-webkit/nw /your/project/folder

# If you are on windows

C:\path\to\node-webkit\nw.exe C:\your\project\folder

# (the paths are only for illustrative purposes, any folder will do)

This will open a new node-webkit window and print a bunch of debug messages in your terminal.

You can optionally add the extracted node-webkit folder to your PATH, so that it is available as the nw command from your terminal.

Your First Application

There is a Download button near the top of this article. Click it and get a zip with a sample app that we prepared for you. It fetches the most recent articles on Tutorialzine from our RSS feed and turns them into a cool looking 3D carousel usingjQuery Flipster.

nw-app-tree

Directory Structure

Once you extract it, you will see the files above. From here this looks like a standard static website. However, it won’t work if you simply double click index.html – it requires Node.js modules, which is invalid in a web browser. To run it, CD into this folder, and try running the app with this command:

/path/to/node-webkit/nw .

This will show our glorious desktop app.

rsz_node-webkit1-1024x625

Our node-webkit app

How it was made

It all starts with the package.json file, which node-webkit looks up when starting. It describes what node-webkit should load and various parameters of the window.

package.json

{
  "name": "nw-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.html",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "window": {
    "toolbar": false,
    "width": 800,
    "height": 500
  },
  "license": "ISC",
  "dependencies": {
    "pretty-bytes": "^1.0.2"
  }
}

The window property in this file tells node-webkit to open a new window 800 by 500px and hide the toolbar. The file pointed to by the main property will be loaded. In our case this is index.html:

index.html

<!DOCTYPE html>
<html>
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Tutorialzine Node-Webkit Experiment</title>

    <link rel="stylesheet" href="./css/jquery.flipster.min.css">
    <link rel="stylesheet" href="./css/styles.css">

</head>
<body>

    <div class="flipster">
        <ul>
            <!-- Tutorialzine's latest articles will show here -->
        </ul>
    </div>

    <p class="stats"></p>

    <script src="./js/jquery.min.js"></script>
    <script src="./js/jquery.flipster.min.js"></script>
    <script src="./js/script.js"></script>
</body>
</html>

And finally, here is our JavaScript file. This is where it gets interesting!

js/script.js

// Mixing jQuery and Node.js code in the same file? Yes please!

$(function(){


    // Display some statistic about this computer, using node's os module.

    var os = require('os');
    var prettyBytes = require('pretty-bytes');

    $('.stats').append('Number of cpu cores: <span>' + os.cpus().length + '</span>');
    $('.stats').append('Free memory: <span>' + prettyBytes(os.freemem())+ '</span>');

    // Node webkit's native UI library. We will need it for later
    var gui = require('nw.gui');


    // Fetch the recent posts on Tutorialzine

    var ul = $('.flipster ul');

    // The same-origin security policy doesn't apply to node-webkit, so we can
    // send ajax request to other sites. Let's fetch Tutorialzine's rss feed:

    $.get('http://feeds.feedburner.com/Tutorialzine', function(response){

        var rss = $(response);

        // Find all articles in the RSS feed:

        rss.find('item').each(function(){
            var item = $(this);
            
            var content = item.find('encoded').html().split('</a></div>')[0]+'</a></div>';
            var urlRegex = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?/g;

            // Fetch the first image of the article
            var imageSource = content.match(urlRegex)[1];


            // Create a li item for every article, and append it to the unordered list

            var li = $('<li><img /><a target="_blank"></a></li>');

            li.find('a')
                .attr('href', item.find('link').text())
                .text(item.find("title").text());

            li.find('img').attr('src', imageSource);

            li.appendTo(ul);

        });

        // Initialize the flipster plugin

        $('.flipster').flipster({
            style: 'carousel'
        });

        // When an article is clicked, open the page in the system default browser.
        // Otherwise it would open it in the node-webkit window which is not what we want.

        $('.flipster').on('click', 'a', function (e) {

            e.preventDefault();
            
            // Open URL with default browser.
            gui.Shell.openExternal(e.target.href);

        });

    });

});

Notice that we are accessing Tutorialzine’s RSS feed directly with jQuery, even though it is on a different domain. This is not possible in a browser, but Node-WebKit removes this limitation to make development of desktop applications easier.

Here are the node modules we’ve used:

  • Shell – A node webkit module that provides a collection of APIs that do desktop related jobs.
  • OS – The built-in Node.js OS module, which has a method that returns the amount of free system memory in bytes.
  • Pretty Bytes – Convert bytes to a human readable string: 1337 → 1.34 kB.

Our project also includes jQuery and the jQuery-flipster plugin, and that’s pretty much it!

Packaging and Distribution

You most certainly don’t want your users to go through the same steps in order to run you application. You wan’t to package it in a standalone program, and open it by simply double clicking it.

Packaging node-webkit apps for multiple operating systems takes a lot of work to do manually. But there are libraries that do this for you. We tried this npm module – https://github.com/mllrsohn/node-webkit-builder, and it worked pretty well.

The only disadvantage is that the executable files have a large size (they can easily hit 40-50mb) , because they pack a stripped down webkit browser and node.js together with your code and assets. This makes it rather impractical for small desktop apps (such as ours), but for larger apps it is worth a look.

Conclusion

Node-webkit is a powerful tool that opens a lot of doors to web developers. With it, you can easily create companion apps for your web services and build desktop clients which have full access to the users’s computer.

You can read more about node-webkit on their wiki.

Node.js: Five Things Every PHP Developer Should Know

Node.js: Five Things Every PHP Developer Should Know

I recently started working on a few Node.js applications. Coming most recently from PHP (and Drupal in particular), I found the transition to Node.js to be surprisingly easy. Pleasurable, in fact. But I had to learn to think differently about a few things.

Below I list the five things I think every PHP developer should know about Node.js.

1. Node.js Is Built On Chrome’s JavaScript Engine

Google’s browser, Chrome, has a notoriously fast JavaScript engine called V8. And this JavaScript engine can be cleanly separated from the web browser. Node.js is built on V8. This is one of the main reasons why Node.js is so fast.

This has several positive implications for you, the developer:

  • You don’t need to learn a new “dialect” of JavaScript. I find myself referencing Chrome’s and Mozilla’s JS documentation all the time, because Node works the same way.
  • With V8’s JIT (Just In Time) compiling, apps run at near-native speeds (benchmarks indicate it’s much faster than PHP and Ruby, in terms of running analogous computational tasks).
  • As V8 improves, Node will too.

2. Node.js Isn’t (Just) A Web Server or Platform

Unlike PHP, Node.js is not “web centric” (yes, you can run CLI apps in PHP, but that wasn’t the original intent). Node.js is a general-purpose JavaScript runtime with a host of powerful libraries — one of which happens to provide an HTTP/HTTPS server implementation.

But you can do much more with Node. It is easy to build command line clients and other TCP/IP servers.

On the one hand, this is great news. Node.js is so flexible.

On the other hand, since Node.js isn’t HTTP-centric, you may find yourself having to implement code to do things once provided for you by the framework. In other words, in node, there is no$_GET.

3. Node.js Is Object-Oriented (In That Weird JavaScript Way)

I love jQuery. But it’s made me lazy. It’s made it very easy to write quick and dirty scripts without thinking about architecture. When using JavaScript for a few pieces of browser bling, perhaps this isn’t a bad thing.

But Node’s clearly not about browser bling. It’s about application building. Which means architecture. When you write code in Node.js, you’re going to want to get neck-deep in JavaScripts prototypal object model.

Having that strong 10-years-in-Java background, I thought that JavaScript’s weird prototype system would drive me crazy. And sometimes it does. But surprisingly, I’m falling in love with it. Node.js (and NPM, the amazing Node Package Manager) make such good use of the prototypal JavaScript system that merely writing code “like they do” helped me clear many of the hurdles that my Class/Interface mind thought would be hard to grok.

4. Evented I/O?

Now we’re to the most controversial aspect of Node.js. Node itself runs in one thread. ONE! (Compare this to your typical Apache/PHP system where a dozen or more PHP instances are running at once.) Yet somehow it is fast and efficient.

What’s the secret? Sharing execution time, and offloading intensive IO processes to other threads.

I could go off on a long jargon-filled tangent about the benefits and drawbacks of “evented I/O”, but instead I’ll stick to the practical: When writing in Node.js, you need to think a little harder about whether your task is slow (and I/O bound) or fast. Use asynchronous functions with callbacks or event handlers for the slow work.

The important thing is to make sure that your application code doesn’t allow one request to monopolize the main Node process for too long without giving opportunities for other requests to get some work done.

5. Package Management is a Must!

Be honest. Do you love PEAR? Do you turn almost all of your code into PEAR or PECL packages? Not that many PHP developers do (and a surprising number of them don’t even know what PEAR packages are!).

You probably don’t want to carry that mentality over to Node.js.

  • Node.js is designed to be a minimalistic framework. 90% of the stuff you find in PHP’s core will not be present in Node.js’s core. Need an example or two? Database drivers? Not in Node’s core. Mail libraries? Not in Node’s core. HTML support? Not in Node’s core.
  • But a modular architecture is in Node’s core. And you will use it because it is awesome.
  • The npm tool (Node Package Manager) is the second thing you should download — right after Node. With it, a world of Node.js libraries will be available to you. Drivers, parsers, formatters, servers… there are thousands of packages.
  • Building and publishing your own packages is dead simple. I released my first one only a few days after starting with Node. It’s just that easy.

If you’re a Drupal developer, you can think about Node’s packaging system as something similar to Drupal modules — but with the developer (and not site-builder) in mind.