Skip to content

Instantly share code, notes, and snippets.

@lemonskip
Created June 12, 2013 08:56
Show Gist options
  • Save lemonskip/5763826 to your computer and use it in GitHub Desktop.
Save lemonskip/5763826 to your computer and use it in GitHub Desktop.
As we move forward modularising our apps and building components into one file. We may find that a lot of these components will share the same modules (e.g. third party libs ... jQuery, Backbone etc ). This introduces a problem ... how can we manage these cross deps without complicating the developers workflow and build process of a component. T…
define(function(){
/** Almond JS:START */
var requirejs,require,define;(function(e){function c(e,t){return f.call(e,t)}function h(e,t){var n,r,i,s,o,a,f,l,c,h,p=t&&t.split("/"),d=u.map,v=d&&d["*"]||{};if(e&&e.charAt(0)==="."){if(t){p=p.slice(0,p.length-1);e=p.concat(e.split("/"));for(l=0;l<e.length;l+=1){h=e[l];if(h==="."){e.splice(l,1);l-=1}else if(h===".."){if(l===1&&(e[2]===".."||e[0]==="..")){break}else if(l>0){e.splice(l-1,2);l-=2}}}e=e.join("/")}else if(e.indexOf("./")===0){e=e.substring(2)}}if((p||v)&&d){n=e.split("/");for(l=n.length;l>0;l-=1){r=n.slice(0,l).join("/");if(p){for(c=p.length;c>0;c-=1){i=d[p.slice(0,c).join("/")];if(i){i=i[r];if(i){s=i;o=l;break}}}}if(s){break}if(!a&&v&&v[r]){a=v[r];f=l}}if(!s&&a){s=a;o=f}if(s){n.splice(0,o,s);e=n.join("/")}}return e}function p(t,r){return function(){return n.apply(e,l.call(arguments,0).concat([t,r]))}}function d(e){return function(t){return h(t,e)}}function v(e){return function(t){s[e]=t}}function m(n){if(c(o,n)){var r=o[n];delete o[n];a[n]=true;t.apply(e,r)}if(!c(s,n)&&!c(a,n)){throw new Error("No "+n)}return s[n]}function g(e){var t,n=e?e.indexOf("!"):-1;if(n>-1){t=e.substring(0,n);e=e.substring(n+1,e.length)}return[t,e]}function y(e){return function(){return u&&u.config&&u.config[e]||{}}}var t,n,r,i,s={},o={},u={},a={},f=Object.prototype.hasOwnProperty,l=[].slice;r=function(e,t){var n,r=g(e),i=r[0];e=r[1];if(i){i=h(i,t);n=m(i)}if(i){if(n&&n.normalize){e=n.normalize(e,d(t))}else{e=h(e,t)}}else{e=h(e,t);r=g(e);i=r[0];e=r[1];if(i){n=m(i)}}return{f:i?i+"!"+e:e,n:e,pr:i,p:n}};i={require:function(e){return p(e)},exports:function(e){var t=s[e];if(typeof t!=="undefined"){return t}else{return s[e]={}}},module:function(e){return{id:e,uri:"",exports:s[e],config:y(e)}}};t=function(t,n,u,f){var l,h,d,g,y,b=[],w;f=f||t;if(typeof u==="function"){n=!n.length&&u.length?["require","exports","module"]:n;for(y=0;y<n.length;y+=1){g=r(n[y],f);h=g.f;if(h==="require"){b[y]=i.require(t)}else if(h==="exports"){b[y]=i.exports(t);w=true}else if(h==="module"){l=b[y]=i.module(t)}else if(c(s,h)||c(o,h)||c(a,h)){b[y]=m(h)}else if(g.p){g.p.load(g.n,p(f,true),v(h),{});b[y]=s[h]}else{throw new Error(t+" missing "+h)}}d=u.apply(s[t],b);if(t){if(l&&l.exports!==e&&l.exports!==s[t]){s[t]=l.exports}else if(d!==e||!w){s[t]=d}}}else if(t){s[t]=u}};requirejs=require=n=function(s,o,a,f,l){if(typeof s==="string"){if(i[s]){return i[s](o)}return m(r(s,o).f)}else if(!s.splice){u=s;if(o.splice){s=o;o=a;a=null}else{s=e}}o=o||function(){};if(typeof a==="function"){a=f;f=l}if(f){t(e,s,o,a)}else{setTimeout(function(){t(e,s,o,a)},4)}return n};n.config=function(e){u=e;if(u.deps){n(u.deps,u.callback)}return n};define=function(e,t,n){if(!t.splice){n=t;t=[]}if(!c(s,e)&&!c(o,e)){o[e]=[e,t,n]}};define.amd={jQuery:true}})();
/** Almond JS:END */
/** Compiled Modules of the Component:START */
define('app/internal_mod', ['jquery'], function($){
function TestMod( foo ){
this.foo = foo;
}
TestMod.prototype.displaySomething = function (str) {
document.querySelector('body').innerHTML = str
};
return TestMod;
});
define('app/main', function(){
function MainPlugin() {}
return MainPlugin;
});
/** Compiled Modules of the Component:END */
/**
* Boilerplate code that all components must expose
*/
return {
getRequire: function() { return require; },
setRequire: function( decorated_require ){ require = decorated_require; },
main: 'app/main' // needed because we may have multiple instances of the same plugin
};
});
define([
'underscore',
'when'
], function( _, when ){
function noop() {}
//@TODO: needs further though/work to handle amd plugin notation !
function shouldHandle( dep, reservedNamespace ) {
var path_parts = dep.split('/');
if( reservedNamespace.indexOf( path_parts[0] ) === -1 ) {
return true;
} else {
return false;
}
}
/**
* componentRequire - almondjs require from within the plugin
* reservedNamespace - array of strings (path prefixes that should not be passed through the global require)
*/
function decorateRequire( componentRequire, reservedNamespace ){
return function( deps ){
if( typeof deps === 'string' ) {
/** synchronous require */
if( shouldHandle(deps, reservedNamespace) ) {
/**
* try catch because the error (if any)
* needs to be flagged by the componentRequire (makes debugging easier)
*/
try{
return require(deps);
} catch( e ) {}
}
return componentRequire.apply(false, arguments );
} else {
/**
* async require - need to require each dep independantly so we can handle
* list of mixed deps - some from the global require and some from
* the pluginRequire modules loaded from console
*/
var success = arguments[1] || noop;
var failure = arguments[1] || noop;
var defers = [];
_.each(deps, function( dep ){
var defer = when.defer();
if( shouldHandle(dep, reservedNamespace) ) {
require([dep], function( module ){
defer.resolve( module );
}, function( error ) {
/**
* hmmm not our problem! we tried let the foreingRequire do it
* We will not catch the error here because its not our concern
*/
componentRequire([dep], function( module ){
defer.resolve( module );
});
});
} else {
componentRequire([dep], function( module ){
defer.resolve( module );
});
}
defers.push( defer.promise );
});
when.all( defers ).then(function( modules ){
/** hey all resolved :) */
success.apply( false, modules );
}, function(){
/** hey something did not resolve */
failure.apply( false, modules );
});
}
}
}
return decorateRequire;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment