I'm using RequireJS on my Node.js server to aid in code re-use. I'm sharing modules between client and server, and therefore I want to keep these modules as general as possible.
The problem is that I have a 3rd party library (easeljs) that provides both a client and a server-side implementation, with the server-side implementation provided by npm as 'node-easel'.
The way I expected to deal with this doesn't work. I provided a paths config for the server side application as follows:
requirejs.config({
nodeRequire: require,
paths: {
'easeljs': 'node-easel'
}
})
The above code will first look for node-easel.js in the root directory, before falling back onto node's require('easeljs'), which is not what I want. I want requireJS to fall back onto require('node-easel'). What would be the best way to accomplish this?
I struggled a little with this myself, but actually was able to use a combination of RequireJS map configuration and a NPM module loader. The code is as follows:
requirejs.config({
paths: {
npm: 'helpers/requirejs/npmloader'
},
map: {
'*': {
dust: 'npm!dustjs-linkedin'
}
}
});
And then for helpers/requirejs/npmloader.js:
define({
normalize: function (name, normalize) {
return name;
},
load: function (name, req, onload, config) {
require(name);
}
});
With this you can easily alias NodeJS modules using RequireJS.
In package.json I also use the following:
"main": "./bin/server.js",
"bin": {
"server.js": "./bin/server.js"
}
With top level bin/server,js being a symbolic link to build/init.js and being executable chmod a+x build/server.js.
Instead of using the amdefine loader, which is rather lacking without the ability to use plugins, I use the full requirejs module with NodeJS, and then I just have define be available globally for all my modules as you can see in the code below.
Then src/init.js (or after building - build/init.js) contains the following which might be a useful example:
#!/usr/bin/env node
/**
* @file The AMD loader module configuration.
* @author runelabs <http://github.com/runelabs>
* @version $Id$
* @description
*
* MODULE 'init' OVERVIEW:
* This defines the init RequireJS configuration module,
* in contrast to other modules which are using the AMD define() pattern.
*
*/
/*global require, define, global*/ // using JShint linter
(function() {
'use strict';
var requirejs, mocha, mainProg;
global.requirejs = global.define = requirejs = require('requirejs');
mainProg = ['main'];
var config = {
deps: mainProg,
paths: {
lib: 'lib/',
tests: '../tests',
app: '.',
config: 'models/config',
packages: 'packages',
logger: 'packages/logger/logger',
pkg: 'helpers/requirejs/pkgloader',
npm: 'helpers/requirejs/npmloader',
text: 'lib/requirejs-text/text'
/* ... more paths */
},
map: {
'*': {
marionette:'npm!backbone.marionette',
dust: 'npm!dustjs-linkedin'
}
}
};
requirejs.config(config);
requirejs.onError = function (err, u, l) {
var LOG = require('./packages/logger/logger');
LOG.error('RequireJS error: ', err.requireType);
LOG.error(' mod: ', err.requireModules);
LOG.error(' map: ', err.requireMap);
if (err.requireType === 'timeout') {
LOG.error(' modules: ', err.requireModules);
}
LOG.error('ERR: ', err);
LOG.error('ERR error: ', err.error);
LOG.error('ERR type: ', typeof err);
if (err['toSource']) {
LOG.error('ERR src: ', err.toSource());
}
LOG.error('ERR name: ', err.name);
LOG.error('ERR message: ', err.message);
LOG.error('ERR file: ', err.fileName);
LOG.error('ERR line: ', err.lineNumber);
LOG.error('ERR col: ', err.columnNumber);
LOG.error('ERR stack: ', err.stack);
throw(err);
};
})();
Hope this helps someone else looking to use RequireJS to load stuff from node_modules.
EDIT: A smaller example is from RequireJS creator James Burke at:
https://groups.google.com/forum/#!msg/requirejs/ur_UQLr04rc/sSpM8y87VNMJ