In browsers + Node, what is the scope of a module? - javascript

I'm wondering what the scope of a module is in both browsers and Node. I'm specifically trying to understand whether a module-level variable is created once per app, or many times. Is a new instance of the module created on each import, or is it the exact same module shared across all imports? Many thanks!

There are several JS module flavours - ESM, CommonJS, AMD. Their common trait is that they are evaluated once on first import, at least under normal circumstances. Doing the opposite would make them inefficient for sharing data.
Exporting class instance is a common way to share one instance across the application without making a class a singleton.
The ways that can make a module be evaluated multiple times (intentionally or not) include having many copies of a module, different filename case on import in case-insensitive system, the modification of Node module cache.

Related

Webpack: Is duplicate module loading inefficient?

From my understanding, webpack (and other similar bundlers) ensures that if the same module is required across multiple parts of the app:
That code will only be loaded once
Each time the same module is required, a new instance is created, rather than all sharing the same scope
Firstly, are my above assumptions correct? If so, is it bad optimisation to have multiple instances of the same module being created?
In my example I am creating an app that will be using ThreeJS. This is a rather large library. Many of the modules in my app will want to require this library.
Is it bad practice to keep on requiring a library like this? Or should I be passing a single instance from module to module instead of requiring multiple times?
I'd be interested to know if there are any common patterns for dealing with this, if it is indeed an issue.
This assumption:
Each time the same module is required, a new instance is created,
rather than all sharing the same scope
is wrong for two reasons:
Whether an instance is created or not, will depend on what is returned by the required module (it could return nothing).
Even if the module initialises an instance, only one will be created, as the code in the module is only run once.
With that said, requiring the same module multiple times should have no impact in performance.

Avoiding re-evaluation and dynamically unloading objects called with `require`

i'm studying how nodejs module system works.
I've found so far this literature:
https://nodejs.org/api/modules.html
http://fredkschott.com/post/2014/06/require-and-the-module-system/
http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm
It helps me to understand a few points however is still have these questions:
If i have a expensive resource (let's say database pooling connection) inside a module, how can i make sure that by requiring the module again i am not re-evaluating the resource?
How can i dynamically unload a disposable resource once i already called the 'require' on it?
It's important because i have some scenarios that demands me to make sure that i have a single instance of database pool. because of this i'm exporting modules which are able to receive parameters instead of just require the expensive resource.
Any guidance is very appreciated.
Alon Salont has written an EXCELLENT guide to understanding exports in NodeJS (which is what you're accessing when you call require()) here:
http://bites.goodeggs.com/posts/export-this/#singleton
If you study the list of options for what a module can export, you'll see that the answer to your question depends on how the module is written. When you call require, NodeJS will look for the module loaded in its cache and return it if it already had it loaded elsewhere.
That means if you choose to export a Singleton pattern, are monkey-patching, or creating global objects (I recommend only the first one in your case), only ONE shared object will be created / will exist. Singleton patterns are good for things like database connections that you want to be shared by many modules. Although some argue that "injecting" these dependencies via a parent/caller is better, this is a philosophical view not shared by all, and singletons are widely used by software developers for shared-service tasks like this.
If you export a function, typically a constructor, require() will STILL return just one shared reference to that. However, in this case, the reference is to a function, not something the function returns. require() doesn't actually CALL the function for you, it just gives you a reference to it. To do any real work here, you must now call the function, and that means each module that requires this thing will have its own instance of whatever class the module provides. This pattern is the more traditional one where a class instance is desired / is the goal. Most NPM modules fit this category, although that doesn't mean a singleton is a bad idea in your case.

How do I efficiently declare AngularJS module dependencies?

I have an Angular application which is going to become quite large. For the sake of clarity, I opted for splitting it into different modules, one for each application area. I'm adding components strictly related to an area to the corresponding module, and shared components to an additional common module. All these modules are in turn loaded by a unique main module, that depends on all of these and basically represents the application as a whole.
Now, it turns out that many of the areas need internationalization, so each area's module depends in turn on a translation module to have its string localized. But when I put it all together by means of the main "aggregator" module the translate module ends up with being loaded multiple times, with only one instance actually used.
For instance, let's say my application has the following areas:
Main dashboard
Settings
Documentation
Support
Corresponding modules are declared as follows:
angular.module('app.mainDashboard', [translate]);
angular.module('app.settings', [translate]);
angular.module('app.settings', [translate]);
angular.module('app.support', [translate]);
and the main module looks like this:
angular.module('app.main', [app.mainDashboard, app.settings, app.settings, app.support]);
This approach definitely works, but I bet there is a better way to achieve the same result without repeatedly loading the same dependency. Or perhaps my initial module splitting approach is awkward by itself and in turn it leads to this other inconvenient.

Inherit module in Javascript possible?

I have a module like this :
var myModule= {};
(function( exports ){
init();
exports.doSomething= function(){
return "test";
};
function init(){
initSubscribers();
initListeners();
initForAdmins();//just for the admin
}
//... a lot of functions that maybe doing things depends on if user is admin or normal user
})( myModule );
I have 2 web pages : "Normal page" use "myModule" for normal user and "Admin page" use "myModule" for admin.
Some parts of the module is used by both (normal and admin user) but some parts are specific to the type of user.
I would like to create 2 modules (myNormalModule and myAdminModule) that inherits from a general module (with shared function).
It looks strange to me to "inherit from a module".
My generalModule must be an object or it can be a module ?
You create object types and then inherit from them. You don't inherit from a module. One module can use another module in its own implementation, but that is not inheritance.
So, first create the object structure that you want to use (including inheritance if appropriate) and then, organize that into appropriate modules. And, in organizing your code into modules, a module could define an object type and could then export (e.g. share) that object type and then other modules could either use it or inherit from it. But, the module itself is just a code organizing structure, it isn't an inheritance structure.
So, I'd suggest you figure out your object hierarchy (including inheritance) before you worry about modules and once that is designed, you can then organize it into whatever appropriates modules. For example, if all your object types for this particular problem are pretty much always going to be used together, then they might all be put in one module together.
But, if some object types for this problem might be used by themselves, then it might make sense to break them into their own module for each of sharing only appropriate pieces.
If you have context that you want to share among modules, then there are several different ways to do that depending upon exactly what it is and how it's used. The context could belong to a base object that all other objects inherit from. Or, if the context is more global, it could be stored in one module and then exported to other modules that want access to it.

requireJS : How to structure Javascript for an entire site?

I have 3000+ lines of javascript that I need to get into a sensible/maintainable structure. I have chosen to use requireJS as it has been recommend to me by a few people. I have a bunch of variables that are used throughout the application and need to be available everywhere. I also have a bunch of functions that need to be available everywhere. Apart from these two dependencies most of the code can be divided off into their own modules.
I am having trouble understanding how to manage my main variables so that if one module of code makes changes to the variables the rest of the JS modules will see that change. I think I need to see a few examples that demonstrate how requireJS is intended to work on a larger scale that the examples in the documentation.
If anyone is an experienced requireJS user I would love the hear your tips!
The whole point of RequireJS is to avoid the need for these global variables and global functions.
Can't you wrap those globals into a module, then depend on it in your other modules?
For example, a RequireJS modularized Dojo may be something like:
dojo/cache module
dojo/string module (requires dojo/cache)
dojo/date module (requires dojo/string)
dojo/cookie module (requires dojo/string)
:
:
dojo module (requires everything above, make them all into sub-objects, say, e.g. dojo.cache, dojo.string, dojo.date etc.)
user module #1 (requires dojo)
user module #2 (maybe only requiring dojo/string)
RequireJS gives you better options for encapsulating modules, but it doesn't change Javascript itself at all. As a transition strategy, you can still define your globals inside the function block. Depending on the module that contains these definitions will ensure that it has run before the dependent modules.
Next step would be to assign those methods to an object other than window, and then use that object through the variable received from RequireJS module dependency.
Hopefully by the time you've done this, you might have some insight into a cleaner solution. I refactored (and still am) a single-file project into several files, including optional plug-ins, although I did most of it before adding RequireJS to the mix.
See the RequireJS documentation:
Defining a module
Definition Functions with Dependencies
If the module has dependencies, the first argument should be an array of dependency names, and the second argument should be a definition function. ... The dependencies will be passed to the definition function as function arguments
define(["./cart", "./inventory"], function(cart, inventory) {
// ...
return { ... };
}
);
So I think you can define() your main module like all other modules and make the submodules depend on that main module. Then the module object is passed as an argument to the definition function of a submodule. You don't have to use global variables.
If you want to share information between modules, attach the information to the module object, and have the other modules rely on that module, and check its property.
If you have existing code, you can assign to window.x to provide a global x while you are cleaning it up.

Categories

Resources