RequireJS modules referencing each other - requirejs

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.

Related

Node.js Globalize es6 modules to act like ImportScripts

The question is simple, how do we make es6 modules act like the ImportScript function used on the web browser.
Explanation
The main reason is to soften the blow for developers as they change their code from es5 syntax to es6 so that the transition does not blow up your code the moment you make the change and find out there are a thousand errors due to missing inclusions. It also give's people the option to stay as is indefinitely if you don't want to make the full change at all.
Desired output
ImportScript(A file path/'s); can be applied globally(implicitly) across subsequently required code and vise-verse inside a main file to avoid explicit inclusion in all files.
ES6 Inclusion
This still does not ignore the fact that all your libraries will depend on modules format as well. So it is inevitable that we will still have to include the export statement in every file we need to require. However, this should not limit us to the ability to have a main file that interconnects them all without having to explicitly add includes to every file whenever you need a certain functionality.
DISCLAIMER'S
(Numbered):
(Security) I understand there are many reasons that modules exist and going around them is not advisable for security reasons/load times. However I am not sure about the risk (if any) of even using a method like "eval()" to include such scripts if you are only doing it once at the start of an applications life and to a constant value that does not accept external input. The theory is that if an external entity is able to change the initial state of your program as is launched then your system has already been compromised. So as it is I think the whole argument around Globalization vs modules boils down to the project being done(security/speed needed) and preference/risk.
(Not for everyone) This is a utility I am not implying that everyone uses this
(Already published works) I have searched a lot for this functionality but I am not infallible to err. So If a simple usage of this has already been done that follows this specification(or simpler), I'd love to know how/where I can attain such code. Then I will promptly mark that as the answer or just remove this thread entirely
Example Code
ES5 Way
const fs = require('fs');
let path = require('path');
/* only accepts the scripts with global variables and functions and
does not work with classes unless declared as a var.
*/
function include(f) {
eval.apply(global, [fs.readFileSync(f).toString()])
}
Main file Concept example:
ImportScript("filePath1");loaded first
ImportScript("filePath2");loaded second
ImportScript("filePath3");loaded third
ImportScript("filePath4");loaded fourth
ImportScript("filePath5");loaded fifth
ImportScript("someExternalDependency");sixth
/* where "functionNameFromFile4" is a function defined in
file4 , and "variableFromFile2" is a global dynamic
variable that may change over the lifetime of the
application.
*/
functionNameFromFile4(variableFromFile2);
/* current context has access to previous scripts contexts
and those scripts recognize the current global context as
well in short: All scripts should be able to access
variables and functions from other scripts implicitly
through this , even if they are added after the fact
*/
Typical exported file example (Covers all methods of export via modules):
/*where "varFromFile1" is a dynamic variable created in file1
that may change over the lifetime of the application and "var" is a
variable of type(varFromFile4) being concatenated/added together
with "varFromFile4".
*/
functionNameFromFile4(var){
return var+varFromFile1;
}
//Typical export statement
exportAllHere;
/*
This is just an example and does not cover all usage cases , just
an example of the possible functionality
*/
CONCLUSION
So you still need to export the files as required by the es6 standard , however you only need to import them once in a main file to globalize their functionality across all scripts.
I'm not personally a fan of globalizing all the exports from a module, but here's a little snippet that shows you how one ESM module's exports can be all assigned to the global object:
Suppose you had a simple module called operators.js:
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
You can import that module and then assign all of its exported properties to the global object with this:
import * as m from "./operators.js"
for (const [prop, value] of Object.entries(m)) {
global[prop] = value;
}
// can now access the exports globally
add(1, 2);
FYI, I think the syntax:
include("filePath1")
is going to be tough in ESM modules because dynamic imports in an ESM module using import (which is presumably what you would have to use to implement the include() function you show) are asynchronous (they return a promise), not synchronous like require().
I wonder if a bundler or a transpiler would be an option?
There is experimental work in nodejs related to custom loaders here: https://nodejs.org/api/esm.html#hooks.
If you can handle your include() function returning a promise, here's how you put the above code into that function:
async function include(moduleName) {
const m = await import(moduleName);
for (const [prop, value] of Object.entries(m)) {
global[prop] = value;
}
return m;
}

Using node module in angularjs?

What's the best practice for using external code, e.g. code found in node modules, in angular?
I'd like to use this https://www.npmjs.com/package/positionsizingcalculator node module in my angular app. I've created an angular service intended to wrap the node module, and now I want to make the service use the node module.
'use strict';
angular.module('angularcalculator')
.service('MyService', function () {
this.calculate = function () {
return {
//I want to call the node module here, whats the best practice?
};
}
});
To do this, I would crack open the package and grab the .js out of it. This package is MIT license, so we can do whatever we want. If you navigate to /node_modules/positionsizingcalculator/ you'll find an index.js. Open that up and you'll see the moudle export, which takes a function that returns an object.
You'll notice this is an extremely similar pattern to .factory, which also takes a function that returns an object (or constuctor, depending on your pattern). So I'd do the following
.factory('positionsizingcalculator', function(){
basicValidate = function (argument) {
... //Insert whole declaration in here
return position;
})
and the inject it where you need it:
.controller('AppController', function(positionsizingcalculator){
//use it here as you would in node after you inject it via require.
})
--
Edit: This is good for one off grabs of the JS, but if you want a more extensible solution, http://browserify.org/ is a better bet. It allows you to transform your requirements into a single package. Note that this could result in pulling down a lot more code that you might otherwise need, if you make one require bundle for your whole site, as this is not true AMD, and you need to to load everything you might want one the client, unless you make page specific bundles.
You'd still want to do the require in a factory and return it, to keep it in angular's dependency injection framework.

how to pass a shared variable to downstream modules?

I have a node toplevel myapp variable that contains some key application state - loggers, db handlers and some other data. The modules downstream in directory hierarchy need access to these data. How can I set up a key/value system in node to do that?
A highly upticked and accepted answer in Express: How to pass app-instance to routes from a different file? suggests using, in a lower level module
//in routes/index.js
var app = require("../app");
But this injects a hard-coded knowledge of the directory structure and file names which should be a bigger no-no jimho. Is there some other method, like something native in JavaScript? Nor do I relish the idea of declaring variables without var.
What is the node way of making a value available to objects created in lower scopes? (I am very much new to node and all-things-node aren't yet obvious to me)
Thanks a lot.
Since using node global (docs here) seems to be the solution that OP used, thought I'd add it as an official answer to collect my valuable points.
I strongly suggest that you namespace your variables, so something like
global.myApp.logger = { info here }
global.myApp.db = {
url: 'mongodb://localhost:27017/test',
connectOptions : {}
}
If you are in app.js and just want to allow access to it
global.myApp = this;
As always, use globals with care...
This is not really related to node but rather general software architecture decisions.
When you have a client and a server module/packages/classes (call them whichever way you like) one way is to define routines on the server module that takes as arguments whichever state data your client keeps on the 'global' scope, completes its tasks and reports back to the client with results.
This way, it is perfectly decoupled and you have a strict control of what data goes where.
Hope this helps :)
One way to do this is in an anonymous function - i.e. instead of returning an object with module.exports, return a function that returns an appropriate value.
So, let's say we want to pass var1 down to our two modules, ./module1.js and ./module2.js. This is how the module code would look:
module.exports = function(var1) {
return {
doSomething: function() { return var1; }
};
}
Then, we can call it like so:
var downstream = require('./module1')('This is var1');
Giving you exactly what you want.
I just created an empty module and installed it under node_modules as appglobals.js
// index.js
module.exports = {};
// package.json too is barebones
{ "name": "appGlobals" }
And then strut it around as without fearing refactoring in future:
var g = require("appglobals");
g.foo = "bar";
I wish it came built in as setter/getter, but the flexibility has to be admired.
(Now I only need to figure out how to package it for production)

Require a file within itself in node.js

How do you require a file within itself in node.js? E.g. api.js:
var api = require(./api.js);
What is the best practice for doing this?
You can totally do it. Try this, for instance (in a file named a.js):
exports.foo = 'foo';
var a = require('./a');
console.log(a);
exports.bar = 'bar';
console.log(a);
At the point where require executes, it will return the module a as it exists at the point where require runs so the field foo will be defined but not bar.
There's no point to doing this though. You use require to bring into your current scope an object which would otherwise not be available (namely, a module). But you don't need to do this to access the module you are currently in: it is already fully available.
The code above works because Node has rules to handle cyclic dependencies. And here you have a module which is cyclicly dependent on itself. Rather than go into an infinite loop of requires, Node has require return the module as built up to that point: a partial module. And the modules in a cyclic dependency have to be designed to handle the fact that they may get partial modules.
Cyclic dependencies are to be avoided as much as possible. Most of the time this means refactoring the modules to avoid the mutual dependency by moving functionality into one or more new modules.
So, again, the best practice is to not do this in the first place.

Using a global variable in Node.js for dependency injection

I'm starting out a long term project, based on Node.js, and so I'm looking to build upon a solid dependency injection (DI) system.
Although Node.js at its core implies using simple module require()s for wiring components, I find this approach not best suited for a large project (e.g. requiring modules in each file is not that maintainable, testable or dynamic).
Now, I'd done my bits of research before posting this question and I've found out some interesting DI libraries for Node.js (see wire.js and dependable.js).
However, for maximal simplicity and minimal repetition I've come up with my own proposition of implementing DI:
You have a module, di.js, which acts as the container and is initialized by pointing to a JSON file storing a map of dependency names and their respective .js files.
This already provides a dynamic nature to the DI, as you may easily swap test/development dependencies.
The container can return dependencies by using an inject() function, which finds the dependency mapping and calls require() with it.
For simplicity, the module is assigned to a global variable, i.e. global.$di, so that any file in the project may use the container/injector by calling $di.inject().
Here's the gist of the implementation:
File di.js
module.exports = function(path) {
this.deps = require(path);
return {
inject: function(name) {
if (!deps[name])
throw new Error('dependency "' + name + '" isn\'t registered');
return require(deps[name]);
}
};
};
Dependency map JSON file
{
"vehicle": "lib/jetpack",
"fuel": "lib/benzine",
"octane": "lib/octane98"
}
Initialize the $di in the main JavaScript file, according to development/test mode:
var path = 'dep-map-' + process.env.NODE_ENV + '.json;
$di = require('di')(path);
Use it in some file:
var vehicle = $di.inject('vehicle');
vehicle.go();
So far, the only problem I could think of using this approach is the global variable $di.
Supposedly, global variables are a bad practice, but it seems to me like I'm saving a lot of repetition for the cost of a single global variable.
What can be suggested against my proposal?
Overall this approach sounds fine to me.
The way global variables work in Node.js is that when you declare a variable without the var keyword, and it gets added to the global object which is shared between all modules. You can also explicitly use global.varname. Example:
vehicle = "jetpack"
fuel = "benzine"
console.log(vehicle) // "jetpack"
console.log(global.fuel) // "benzine"
Variables declared with var will only be local to the module.
var vehicle = "car"
console.log(vehicle) // "car"
console.log(global.vehicle) // "jetpack"
So in your code if you are doing $di = require('di')(path) (without var), then you should be able to use it in other modules without any issues. Using global.$di might make the code more readable.
Your approach is a clear and simple one which is good. Whether you have a global variable or require your module every time is not important.
Regarding testability it allows you to replace your modules with mocks. For unit testing you should add a function that makes it easy for you to apply different mocks for each test. Something that extends your dependency map temporarily.
For further reading I can recommend a great blog article on dependency injection in Node.js as well as a talk on the future dependency injector of angular.js which is designed by some serious masterminds.
BTW, you might be interested in Fire Up! which is a dependency injection container I implemented.

Resources