Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting started with Yabble--browser-side CommonJS module loading

Is anyone familiar with Yabble or other browser-side CommonJS loaders?

I'm experimenting with Node.js and would very much like to create Javascript modules which can be used interchangeably on the server side and the client side. This may end up being more a "because it's awesome" kind of thing more so than "because it's practical and useful" kind of thing.

As such, I'm basically trying to get the CommonJS require() method to work on the browser-side, which is exactly what Yabble is supposed to do. I don't really know where to start with it though. I can't seem to find any documentation other than what's found in Yabble's Github readme, and that's not helping much.

Essentially all I've done is put this in an HTML page...

<script src="yabble.js"></script>

<!-- Uses require -->
<script>
    require.setModuleRoot('http://localhost:8030/')
    my_module = require('my_module')
</script>

But anytime I call the require() function all I get a Synchronous require() is not supported. exception thrown.

Can someone help me get started? Where am I supposed to load yabble.js where am I supposed to call require? Is there a special way to run my Javascript modules?

like image 949
Chris W. Avatar asked Mar 09 '11 18:03

Chris W.


2 Answers

When loading Javascript code that will need to use the require() function into the browser, the entry point into that code must be the require.run() function.

e.g., Good:

<script src="yabble.js"></script>

<script>
    require.setModuleRoot('http://localhost:8030/')
    require.run('my_module') // <-- Uses require() function somewhere
</script>

e.g., Bad (Will get the Synchronous require() is not supported error):

<script src="yabble.js"></script>
<script src="http://localhost:8030/my_module.js"></script> <!-- <== Use's require function somewhere -->

FYI, it's pretty nifty how Yabble does this. It will actually statically analyze your Javascript source code, I think basically just using a regular expression to look for the require() method, and then try to pull that .js script from the server, then it does the same static analysis of that .js script, and on and on.

This can be particularly confusing because it will actually load those .js scripts even if the control logic would mean program flow would never reach the require() function. e.g., if you had...

if (False) { require('some_module'); }

... Yabble will still load this module.

like image 169
Chris W. Avatar answered Sep 28 '22 10:09

Chris W.


Synchronous loading of modules in the browser is problematic. A construct like:

var x = require('something_remote.js')

Implies that the browser will halt your code (i.e. block), go and fetch the remote file, parse it, and then return to you the exports. But this does not jive with the single-threaded browser environment - we would be halting the main JavaScript thread (and thus page interactivity for the user) on the performance of the network. So browsers have evolved against this scenario, to favor async loading on their own schedule. There is some good discussion here:

http://www.sitepen.com/blog/2010/07/16/asynchronous-commonjs-modules-for-the-browser-and-introducing-transporter/

One pattern which might work here is that a require() implementation does synchronously block, fetches the file via XHR and then evals it, but that seems to run against all the browser support/infrastructure for async file-based loading. Also I'm curious what implications that would have for the cross-domain primitive of browser security.

So in order to fit the browser async loading model, we'll need to use a callback mechanism like:

require("something.js", function () { // called later, after something.js has loaded! })

It looks like RequireJS is doing this:

http://requirejs.org/docs/start.html

Perhaps give that a shot?

JavaScript environments like NodeJS etc - built with the provision of loading "local" modules from disk, instead of foreign network hosts - can do the synchronous load.

I would greatly appreciate any corrections from JS experts :-)

like image 20
Mike Repass Avatar answered Sep 28 '22 11:09

Mike Repass