One Ring to rule them all, One Ring to find them, One Ring to bring them all and in the darkness bind them.
My goal here is to be able to run my server side JS (written for nodejs) on the browser, without having to change the sources manually nor passing by a "compilation / transformation" process I would have to run before testing on the browser side. Of course I don't want to start a TCP server from the browser, but I'd like to be able to reuse general purpose libraries at ease.
The first problem comes from the fact that there is no isolation (or namespaces) between different modules on browser side, so if there are not wrapped in a function, then you'll end-up polluting your global namespace. The second problem comes from the fact that "require" and "exports" statements are not standard JS, but a proposal from CommonJS, and so won't be defined in the browser by default. Luckily, James Brantly wrote Yabble - Yet Another (CommonJS) Browser Loader, which can solve these two problems (Thanks James!). Here is how we can use it:
Your server has to be able to serve the following JS files: "/wrapped_js/A.js" and "/wrapped_js/B.js". Yabble will fetch those two JS modules and then run A (which can require B, since it has been loaded). The fine part with the "require.ensure", is that it will load JS modules in parallel.
By default, Yabble uses XHR requests to load the JS modules, and then eval them. This is not the most convenient way of using it since you won't be able to debug them. By writting
we ask Yabble to retrieve the module as scripts files; but the modules code then need to be wrapped as:
Here we say that 'B' depends of 'A', so Yabble will ensure A has been loaded before running B. If we know for sure all dependencies are loaded, we don't have to specify them though.
Yabble features a tool that can wrap the modules for us, but it's pretty static (and I don't want to run it every time I change my sources). So I wrote some code (part of nodetk) that automatically serve JS files: you just have to specify which modules / packages / static files you want to serve, and it will do so. It also wraps automatically JS module files on the fly.
Example of use (on server side):
Now with this code, on client side, we can do any of the followings:
For a complete working example, I encourage you to have a look at nodetk tests, which are running on both server and client side (except for modules which can not run on browser): http://github.com/AF83/nodetk/tree/master/src/nodetk/browser_tests/ .