Node.js and client sharing the same scripts

2020-03-10 05:48发布

问题:

One of the theoretical benefits from working with Node.js is the possibility to share the same scripts between clients and the server. That would make it possible to degrade the same functionality to the server if the client does not support javascript.

However, the Node.js require() method works on it's own. In the script you load, you can add stuff to this or exports that will later be available in the object that fetched the script:

var stuff = require('stuff');
stuff.show();

In stuff.js:

this.show = function() {
    return 'here is my stuff';
}

So, when re-using this script on the client, the .show() method will be added to the window scope. That is not what we want here, instead we would like to add it to a custom namespace.

My only solution so far is something like (in stuff.js):

var ns = typeof exports == 'undefined' ? (function() {
    return window['stuff'] = {};
})() : exports;

ns.show = function() {
    return 'here is my stuff';
}

delete ns; // remove ns from the global scope

This works quite well since I can call stuff.show() on the server and client. But it looks quirky. I tried searching for solutions but node.js is still very new (even to me) so there are few reliable resources. Does anyone have a better idea on how to solve this?

回答1:

In short, if you want to re-use scripts don't use Node.js specific stuff you have to go with the lowest common denominator here, the Browser.

Solutions are:

  1. Go overkill and use RequireJS, this will make it work in both Node.js and the Browser. But you need to use the RequireJS format on the server side and you also need to plug in an on the fly converted script...

  2. Do your own loader

    1. Wrap your re-use scripts both on the server and client side with an anonymous function
    2. Now create some code that users call(module) on that function, on the Node side you pass in this for the module, on the client side you pass in a name space object
  3. Keep it simple and stupid, as it is now, and don't use this in the module scope on the Node.js side of things

I wish I could give you a simple out of the box solution, but both environments differ to much in this case. If you really have huge amounts of code, you might consider a build script which generates the files.