RequireJS: Dependency Loop? - requirejs

I have a question related to RequireJS as I am newbie using it. I understand it includes adding dependencies in module (JS files) by including the dependency in define. Lets say I have two files file1.js and file2.js and both dependent on each other. What would happen if I do the following:
file1.js
define(SomeDependency 1, file2, ..., SomeDependency N){
}
file2.js
define(SomeDependency 1, file1, ..., SomeDependency N){
}
Would the above code create some error like dependency loop or some other javascript error?

Related

Importing typescript definitions for my bundled javascript library

I have a library I wrote in typescript, it contains multiple files and an index.ts file that contains all the exports of the library.
I used webpack to compile the entire library into a single index.js file but I'm having trouble importing it WITH type definitions.
Lets say this is my library:
src
-- index.ts
-- items-dal.ts
-- items-bl.ts
output
-- index.js
-- index.d.ts
-- items-dal.d.ts
-- items-bl.d.ts
webpack.config
ts.config
package.json
So I copied the output folder to my other project but when I try to create a class that inherits one of my library's classes I get an error:
// user-dal.ts
const { ItemsDAL } = require("./output");
class UsersDAL extends ItemsDAL {
constructor() {
super("users");
}
}
export default new UsersDAL();
// usage
import usersDal from "./users-dal.ts";
usersDal.getAll() // <-- Property "getAll" doesn't exist on type usersDal
I know I can work around this by using require() but I'd prefer having the actual typings in my other projects.
The reason I'm doing this is because I'm obfuscating the index.js file but I don't mind exposing the name of the functions it contains. It may sound counter-productive but it provides enough security for my needs.
Is there a way to make typescript detect the d.ts files? (or any other way to have obfuscated code with typings)
Just add a "types" declaration to your package.json.
{
...
"main": "./output/index.js",
"types": "./output/index.d.ts",
...
}

jasmine-node - including helper

I am trying to test my Meteor application with jasmine-node. I've stubbed out some methods of Meteor framework in the helper (spec_helper.js):
var Meteor = {
startup: function (newStartupFunction) {
Meteor.startup = newStartupFunction;
},
Collection: function (collectionName) {
Meteor.instantiationCounts[collectionName] = Meteor.instantiationCounts[collectionName] ?
Meteor.instantiationCounts[collectionName] + 1 : 1;
},
instantiationCounts: {}
};
At this point I need to run the code in spec_helper.js (something equivalent of including a module in other languages). I've tried the following, but no success:
require(['spec_helper'], function (helper) {
console.log(helper); // undefined
describe('Testing', function () {
it('should test Meteor', function () {
// that's what I want to call from my stubs...
// ...it's obviously undefined
Meteor.startup();
});
});
});
Any help would be greatly appreciated.
jasmine_node will autoload helpers (any file containing the word helpers) from within your spec directory.
NOTE: you can cheat and use helper instead since it's a substring of helpers...makes more sense if you split helpers out across multiple files...singular vs plural.
If you're executing your specs from specs/unit, then create a file named specs/unit/meteor-helper.js, and jasmine_node will automagically source it for you. It will load files with the extension .js if your specs are written in vanilla JavaScript. If you pass the --coffee switch on the command line or via your grunt task config (you may even be using gulp if you're ambitious), then it will load helpers with the extensions js|coffee|litcoffee.
You should export a hash from each helper file as follows:
specs/unit/meteor-helper.js
// file name must contain the word helper
// x-helper is the convention I roll with
module.exports = {
key: 'value',
Meteor: {}
}
Then, jasmine_node will write each key to the global namespace.
This will allow you to simply type key or Meteor from your specs, or any system under test (typically code inside your lib folder that the specs are executing assertions against).
Additionally, jasmine_node will also allow you to suppress the loading of helpers via the --nohelpers switch (see code or README for more details).
This is the proper way to handle helpers for jasmine via node. You may come across some answers/examples that reference a jasmine.yml file; or maybe even spec_helper.js. But keep in mind that this is for ruby land and not node.
UPDATE: It appears jasmine-node will only source your file if it contains the word helpers. Naming each helper file x-helper.js|coffee|litcofee should do the trick. i.e. meteor-helper.coffee.

RequireJS modules referencing each other

Im using requirejs to load several modules of a web app im building but am struggling to understand something. I have my main module requiring it dependancies but the other defined modules all reference each other in someway. so lets say the 'project/func' module may call a save function in the 'project/save' module. Now most of my code has resulted in undefined being errored.
From reading online maybe Ive hit something known as a circular reference?? Im not quite sure. I guess I need to know what Im doing wrong and how I should be doing it. Ive tried to put an example below with the main file calling the bootstrap method in one of the modules but that module calls another module at some point. This is just a small example. the real app has many many more modules and they all need to run functions inside each others if that makes sense.
//main require
require(['jquery', 'jqueryui', 'project/save', 'project/funcs', 'project/spec'], function($, ui, proSave, proFunc, proSpec){
proFunc.bootstrap();
});
//project/save
define(function(){
var save = function(){
//do some save stuff here
}
return {
save: save
}
});
//project/funcs
define(['project/save'], function(proSave){
var funcs = {
bootstrap: function(){
//do some stuff
funcs.func1();
},
func1: function(){
//do some stuff and save
proSave.save();
}
}
return {
funcs: funcs
}
});
RequireJS has documentation on circular dependencies that explains how to handle them:
If you define a circular dependency (a needs b and b needs a), then in this case when b's module function is called, it will get an undefined value for a. b can fetch a later after modules have been defined by using the require() method (be sure to specify require as a dependency so the right context is used to look up a):
//Inside b.js:
define(["require", "a"],
function(require, a) {
//"a" in this case will be null if a also asked for b,
//a circular dependency.
return function(title) {
return require("a").doSomething();
}
}
);
So you have to write your code to be able to work with the fact that module definitions in circular dependencies will initially be undefined. The details of how you accomplish this are dependent on the specific structure of your application.
These words of wisdom, from the RequireJS documentation, are well worth paying attention to:
Circular dependencies are rare, and usually a sign that you might want to rethink the design.
[Emphasis added.] Very often, if module A depends on B and B depends on A, there's a subset of functionality to be extracted either from A or B and moved into a module C which would allow A to depend on C rather than B, and B to depend on C rather than A, and break the circular dependency. For the sake of everyone working with such code, this is the best route to take. Then, in the rare cases where the circularity cannot be removed, the documentation I cited above tells you how to approach it.

Requiring the same local node module from two directories results in two copies

I have a module (server.js) in the root of my project structure. It includes a module in a directory called lib:
var mongo = require('./lib/MongoUtils');
Another module in the lib directory also needs the 'MongoUtils' module, so it does:
var mongo = require('./MongoUtils');
The problem is I end up with two copies of the object (which is bad as it has some system resources like DB connections, etc.).
I've read the Node.js caching caveats documentation (http://nodejs.org/api/modules.html#modules_module_caching_caveats) and so it seems the problem is that I'm referring to the same module with two different paths and thus Node.js gives me two copies. Is this understanding correct?
How can I work around this? I didn't want to just dump my modules in node_modules since that's managed by npm via my package.json (and .gitignore-d). I thought about putting my local modules in the package.json (assuming that's possible), but then I'd need to be running 'npm install' whenever I make a change.
If this can't be done cleanly, I'll simply load the module in one place and pass it around, but that doesn't sound scalable if this occurs with lots of my modules.
I solved it. It turns out I typoed the capitalization of one of my modules. Node.js happily loaded the module and it worked fine, the only side effect was that I got the module loaded twice.
Here's an example. Note the capital B in the require statement in lib1.js.
main.js:
var lib1 = require('./lib/lib1')
, lib2 = require('./lib/lib2');
lib/lib1.js:
var lib2 = require('./liB2');
lib/lib2.js:
function MyClass() {
console.log('Constructor called');
}
module.exports = new MyClass();
If you run "node main.js" you'll get the following output:
Constructor called
Constructor called
If you fix the capital B in lib1.js and run it again, you'll see:
Constructor called

How does AMD (specifically RequireJs) handle dependancies across multiple modules

I have my main initialization script which calls require() and one of the dependencies is a utilities framework, but some of the other modules that I'm specifying via require() also themselves have defined this framework as a dependency.
For example (init.js):
require(['module-a', 'module-b', 'module-c'], function(a, b, c){
// where module-c is the framework
});
And then in 'module-a' I have:
define(['module-c'], function(c){
// utilize module-c framework
});
So how does AMD/RequireJs handle this scenario, does it load the same framework twice?
Any help appreciated.
Kind regards,
Mark
It will only be loaded once, both of the above modules will get the same module value for 'module-c'.
Incase its useful to others - Here's a situation I came across where a module was loaded twice:
For the following project structure:
~/prj/js/app/fileA.js
~/prj/js/app/util/fileB.js
~/prj/js/ext/publisher.js
where the RequireJs baseurl is ~/prj/js/app
fileA.js refers to the external (ext) dependancy publisher.js as:
//fileA:
define(['../ext/publisher'], function(){});
But fileB.js refers to the same dependancy with a different path:
//fileB:
define(['../../ext/publisher'], function(){});
In short, for both files, the dependency paths are different although the dependancy is in the same location. In this case, publisher.js gets loaded twice.
Use Firebug's Net tab to see it loading twice:
This is easily fixed using paths to configure the external folder path (as explained in the require_js docs):
requirejs.config({
paths: {ext: '../ext'}
});
After setting paths, the dependency is loaded just once with fileA.js and fileB.js both using the same dependency path as follows:
//fileA:
define(['ext/publisher'], function(){});
and
//fileB:
define(['ext/publisher'], function(){});

Resources