Nodejs is cool but
« Tuesday, June 18, 2013 »

nodejs stupidity

I have to say that I'm a big fan of nodejs. I think it is one project that really changes how people are using javascript.

But it might be just a rant. I came across a problem recently. Not that windows is my platform of development of choice. But it happens that the choice. I simply don't have it. Compiling nodejs on windows, people did it. And it works. I won't say that it works very well since to be honest I have windows related problem. I can even say that I'm not the only one having problems with windows.

The source of problems in most part is related to windows actually. Windows has for path separator “\”. Sounds ridicule but this is one problem that probably most languages/frameworks figured out.

Nodejs require function gets a module id for name. It's not really clear in the docs what is a path id, but it's clear that it's something that can be resolved to a filename.

First problem I see is that any id not starting with a dot is going to search for a global path instead of locally. It won't even try to search locally. This isn't a huge deal when you get used to it. But once you have dynamically loaded modules using require.

For example, you want to load every modules in a folder. One could be tempted to write something like this.

1
2
3
4
5
6
var fs = require('fs');
var modules = [];

fs.readdirSync('.').forEach(function(file) {
    modules.push(file);
});

This clearly will fail but we could improve the current code to look for relative paths.

1
2
3
4
5
6
7
var fs = require('fs');
var path = require('path');
var modules = [];

fs.readdirSync('.').forEach(function(file) {
    modules.push(path.join('.', file));
});

This way it's much more subtle, you could expect it to work but it won't. The path module is actually normalizing all dots in a path. So even that will give the same thing as the first example. So right, lets do this much more differently. We still want it to work across all platforms.

1
2
3
4
5
6
7
var fs = require('fs');
var path = require('path');
var modules = [];

fs.readdirSync('.').forEach(function(file) {
    modules.push('.' + path.sep + file);
});

We're appending the separator to the dot to get a valid path. But it won't work! On windows, it won't work to be more precise. We have to use the the '/' separator instead of the system one. In other word, any use of the path module has to be stripped to remove the system separator.

We'll have something like this:

1
2
3
4
5
6
7
var fs = require('fs');
var path = require('path');
var modules = [];

fs.readdirSync('.').forEach(function(file) {
    modules.push('./' + file);
});

Sounds better but we're still not there yet. What if the file variable will be an actual path. require will fail to resolve the path locally. For that reason, we're pretty much forced to remove the sep from file if any is present.

1
2
3
4
5
6
7
var fs = require('fs');
var path = require('path');
var modules = [];

fs.readdirSync('.').forEach(function(file) {
    modules.push('./' + file.replace(/\\/g, '/'));
});

For the sake of having it work on windows, we have to strip manually separators whenever they are required. Append the dot because it get stripped. I've seen similar things in other modules and I've seen where people forgot to do it and without a testing army. It's possible that it's going to be missing in a module and you'll be the winner.

My take on this is that how nodejs requires module is terrible. Having to do this to send an invalid path to resolve a file while we could send a valid path to the file sounds terribly stupid. It forces people to write such workaround to make it work correctly on any platform.

What makes it even funnier is how Windows is actually flexible on the path matter. It accepts the “/” instead of “\”. If you try to do:

1
fs.readdirSync('/')

It will open the root of the main disk letter. But the path module returns you a windows specific path that isn't well supported in the framework. But you can't ask the path module to return something with a different path separator.

And what really pissed me off is when reported it as a bug in nodejs. It got automatically closed as “the module” part is frozen… So what the module will never ever get fixed or updated? What kind of crap is that. I'm not a fan of windows but if I was writing nodejs, I'd make sure to make windows specific fix in other modules aren't spawning here and there because the internal of the project isn't able to handle platform speficif paths.

comments powered by Disqus

Copyright © 2015 Loïc Faure-Lacroix