I find libraries such as Require.js to be too complicated to trust them.
I put all my client-side JS files into ./src directory and watch them with Node.js server. When any file in ./src is added or modified then server automatically copies it to ./build directory and wraps it with additional code required by module loader.
This way I can use (almost) the same syntax for handling modules on both client- and server-side, e.g. I can write client-side script which looks like this:
var button = require('widgets/button.js').button;
var toggleButton = Object.extend(button, {
label: 'Toggle me',
});
exports.toggleButton = toggleButton;
There's a tradeoff here, which is that you'll have to stick to a strict subset of conventional Node. Not just the builtin libraries (fine, that's expected), but basic conventions.
For instance, your approach doesn't support assigning to `module.exports` (just a few more lines of code), relative paths (a few dozen more lines), or the path resolution used by `require.resolve` (a few dozen more).
For small apps it's probably fine, and I've used something very similar. But it's not always easy to decide "this will be a small app" up front. And then there's the issue that even if your app is small, `require` will be doing something very different in Node (complex path resolution) than in the browser, and it could lead to confusing results or a lying test suite.
What I didn't like about Require.js is having to wrap so many portions of my code into callback functions and not being able to merge and minify code on the fly.
We ended up using Browserify instead. It's a Node.js module that lets you use CommonJS-style require in your client-side code. Browserify scans your code for all requires, figures out in which order the dependencies should be loaded and merges the code. Optionally, it lets you compile CoffeeScript on the fly or use filters, such as UglifyJS (to minify the output). Another great advantage, IMO, is that Browserify can package most Node.js modules for client-side use. Instead of downloading & distributing JS libs, you can manage them as modules via NPM and require them as you would in Node.js apps. Browserify will grab the code from the module and package it for you.
However, if you can't use Node.js on your server, Require.js is definitely the way to go.
I agree. Define-wrapping is a pain to do manually.
Browserify is great with Node.
For a slightly different take on how to share code with the server, you might also want to check out https://github.com/clux/modul8 : )
I most definitely agree with this. Though our company has approached it a little differently than you, the combination of Require.js and Backbone.js (with Zepto.js too) has allowed us to make totally flexible HTML5 apps that are easy to test and maintain and once optimised (using r.js that comes with Require.js), we have something very nippy too.
I think it's a great combination! And after finishing three commercial projects with it we have yet to run into any brick walls... Unlike with many other JS MVC frameworks, which in my opinion, try to do too much for you.
That approach may fit the need of a modularity but it doesn't solve the remaining issues. To me, the most important issue is to make both backend and frontend dependencies same.
I haven't documented yet but there is something I'm working on for a while, OneJS. It generates a single, stand-alone JavaScript file, not requiring coder to make any change on a CommonJS code. The built file it generates can be run at any platform that doesn't support CommonJS, such as web browsers. It means that we can use the great dependency mechanism NPM provides in our frontend apps.
The basic reason behind my motivation is that I'm looking for a simple solution developed for the all javascript environments with no commonjs support, not only web browsers. Besides of it, it's better to have same dependencies in both backend and frontend, taking advantage of using NPM. Imagine a test script that should be run by both NodeJS and Internet Explorer 6. What is the current most low-cost way to do it?
I put all my client-side JS files into ./src directory and watch them with Node.js server. When any file in ./src is added or modified then server automatically copies it to ./build directory and wraps it with additional code required by module loader.
This way I can use (almost) the same syntax for handling modules on both client- and server-side, e.g. I can write client-side script which looks like this:
And it will automatically get compiled into: The client-side framework for handling such modules takes 28 lines of code: https://gist.github.com/1287050Unless you are writing really large apps, this approach seems to be much cleaner, just remember to combine and minify all modules before deployment.