Skip to content

Instantly share code, notes, and snippets.

@Deraen
Created December 14, 2014 11:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Deraen/055c3b1a06e0fb90a760 to your computer and use it in GitHub Desktop.
Save Deraen/055c3b1a06e0fb90a760 to your computer and use it in GitHub Desktop.
Necessitate.js, POC JS modules

Feb 2014, not used, not maintained

Necessitate.js

Does RequireJS seem to complicated? You don't like that Browserify requires compilation while developing?

This is a library to implement simple modules.

  • Function params used to define dependencies

It won't offer:

  • Async loading
  • Loading third party libraries

Usage

List all your scripts on your index.html.

var ns = necessitate.ns("your-app");
ns.contant("FOO", {stuff: 5});
ns.module("util", function() {});
ns.module("dep", ["util", function(u) {
  // Annotated deps
}]);
ns.module("404", function() {});
ns.module("app", function(dep) {
  // 404 can't be used as function param but you could do following (though it would be better to name module differently):
  var error404 = ns.require("404");
  // Deps parsed from function parameters
  return {start: function() {}};
});

// Start app when dom is ready
$(document).ready(function() {
  ns.require("app").start();
});

Grunt

NOTE: This is only to optimize app for distribution.

Use grunt-usemin to generate concat etc. configuration. If your using uglifyjs, be sure to include following options or minifed code wont work:

{
  uglify: {
    options: {
      mangle: false,
      compress: {
        unused: false,
      },
    },
  },
}

TODO

  • Tests
  • Investigate performance difference between annotad and non-annotated modules.
    • ngmin like precompiler to annotate modules?
  • Proper example project
(function(target, _) {
"use strict";
var packages = {};
// Use: module("router", function(util, lifecycle) { ... });
// Or: module("router", ["util", "lifecycle", function(u, l) { .. });
// Inspiration and regexps from: https://github.com/angular/angular.js/blob/master/src/auto/injector.js#L63
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
function Module(ns, name, builder) {
var requires;
if (_.isArray(builder)) {
requires = _.initial(builder);
this.builder = _.last(builder);
} else if (_.isFunction(builder)) {
var fnText = builder.toString().replace(STRIP_COMMENTS, "");
var args = fnText.match(FN_ARGS);
requires = _(args[1].split(FN_ARG_SPLIT)).map(function(arg) {
return arg.replace(FN_ARG, function(all, underscore, name) {
return name;
});
}).filter(function(arg) {
return arg !== "";
}).value();
this.builder = builder;
} else {
throw "ERROR: Module builder should be either a Array or Function";
}
var module;
this.get = function() {
if (!module && this.builder) {
var context = {};
try {
// console.log(requires);
module = builder.apply(context, _.map(requires, ns.require)) || context;
} catch(e) {
throw "ERROR: Couldn't get module '" + name + "'\n" + (e.stack || e.message || e);
}
}
return module;
};
}
function Constant(val) {
this.get = function() {
return val;
};
}
function Package(name) {
var modules = {};
this.require = function require(name) {
var module = modules[name];
if (!module) throw "ERROR: Unknown module: '" + name + "'";
return module.get();
};
this.module = function(name, builder) {
// console.log("Registering", name);
var m = modules[name];
if (!m) {
m = new Module(this, name, builder);
modules[name] = m;
}
return m;
};
this.constant = function(name, val) {
// console.log("Registering", name);
modules[name] = new Constant(val);
};
}
function namespace(name) {
var p = packages[name];
if (!p) {
p = new Package(name);
packages[name] = p;
}
return p;
}
target.necessitate = {
ns: namespace,
};
})(window, _);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment