Webpack use one module throughout different files - javascript

I currently have my js files layed out as such
file.js
anotherFile.js
anotherFile2.js
db.js
I want to be able to include the db.js in file.js,anotherFile.js and anotherFile2.js. Do I need to import db.js into every single file or is there a way that I can import it once to be used throughout the project.
file.js imports anotherFile.js and anotherFile2.js but all use db.js
Thanks in advance.

Do I need to import db.js into every single file...
That's best practice, yes. More specifically: You import the parts you need from it. (Don't worry, it's only loaded once.) Otherwise, you're back in the land of globals everywhere, which is what modules are intended to help you avoid, because the global namespace is crowded and conflicts are easy to run into.
You could create globals in db.js, load it from file.js, and have anotherFile.js and anotherFile2.js rely on those globals, but it's strongly discouraged. Explicit relationships between modules don't only help the browser, IDE, and bundler; they help the programmer, too.

Related

if everything in node is a module than what is the point of modules in NestJs?

why not simply use folders instead of modules if the only purpose is to make the structure more organized?
It is weird because it does not seem necessary since every file is a separate module in node js and if i need anything i have to import it using the import statement anyways so what is the point of specifying the imports and exports in a module? does it affect the dependency injection if i just import what i need without using modules(#Module decorator) or something similar?
NestJs has opted to design their framework with dependency injection as one of its core principals. Ie, you write your code just using the name/type of the services you want to use, and then a different piece of code is responsible for finding that service, knowing how to construct it, and then passing it in to you.
Native import/export doesn't have a system for dependency injection, so the main thing that the #Module decorator does is organize the metadata needed for the injector system.

What is the standard approach to ES2015 modular architecture?

I think I now mostly understand (in theory, at least) how ES2015 Modules work.
What I don't understand (and this is far from insignificant) is how to enable module scripts to inform my main script.
Usually, at the bottom of my HTML document, I have something like the following:
<script src="/global-script-is-a-classic-script.js"></script>
That's it. No defer, no async and no type="module".
I may wish to write some optional modules which declare functions, calculate variables and objects and then make all the declared and calculated values available to global-scripts.js:
<script src="/module-script-1.mjs" type="module"></script>
<script src="/module-script-2.mjs" type="module"></script>
<script src="/module-script-3.mjs" type="module"></script>
Naturally each of these module scripts will contain an exports statement.
But... how do I then import what these module scripts calculate into my global-script.js?
I can't use import - because that only works in a Module Script - and (unless I'm mistaken) it seems like it would be a bad idea to have global-scripts.js as anything other than a Classic Script.
So, do I now need to have two global scripts?
<script src="/global-script-is-a-classic-script.js"></script>
<script src="/module-mothership-is-a-module-script.js" type="module"></script>
Or is there an alternative standard architecture which we're all supposed to be using?
It seems you aren't really understanding the change in design philosophy with a module architecture. You don't make things global. A module imports the other modules that it needs and gets its capabilities from the import, not from some global set of functions. In a modular architecture, there would be NO global script. That's why your thinking isn't quite fitting into the modular architecture.
exports is a means of making certain entry points or data publicly accessible to anyone who imports the module while keeping everything else local to the module. One must import the module to get access to these entry points.
So, is exports intended for communication between sub-modules and modules then, rather than for between modules and a global script? That is to say modules never export, only sub-modules do?
Mostly. But, even a top level module could have exports. They wouldn't be used for anything in the project in which it was a top level module, but it could perhaps be used in a different project where it wasn't a top level module and was imported by some other module. The module architecture gets you to think about code reuse and code sharing without having to do a lot of extra work. The normal way you write your project should automatically create a bunch of reusable code.
That might have been the final piece of the puzzle I needed. So exports is just for sub-modules (and sibling-modules), then? Standalone, self-contained top-level modules don't need exports because any functionality happens right there in the module - the data never needs to go anywhere else. (Is that right?)
Yes. Unless you might want to be able to reuse that module in another project where you did import it and did want to import some entry points or data.
I may wish to write some optional modules which declare functions, calculate variables and objects and, after calculation, make all the declared and calculated values available to global-scripts.js. But... how do I then import what these module scripts calculate into my global-script.js?
You will get rid of your global script entirely in a module design. You will have a top level module that imports other modules.
So, do I now need to have two global scripts?
Nope, you get rid of the global script and you don't make things global any more.
Or is there an alternative standard architecture which we're all supposed to be using?
The module architecture:
Top Level Module
import module1
import moduleA
import moduleZ
import moduleB
import module2
import moduleB
import moduleC
import module3
import moduleA
import moduleD
This can go to any arbitrary depth as needed. Modules are cached and only initialized once so importing the same module from more than one place is perfectly fine and perfectly efficient.

how import works in modules imported into Angular

The documentation I've read is rather hand-wavy about what exactly import does in Javascript, particularly in the Angular framework. I get that it imports modules from another file that has one or more exports. But there are many permutations of its syntax, and not all are discussed with much detail. I'm currently having a very hard time with the #asymmetik/ngx-leaflet-markercluster module. When I try to compile my Angular app, I get a message reading "Can't resolve 'leaflet.markercluster' in 'C:\sca_root\city8\node_modules#asymmetrik\ngx-leaflet-markercluster\dist\leaflet-markercluster" -- this is in reference to a line that reads simply
import 'leaflet.markercluster';
This seems to me (and I know, perhaps I am making too many assumptions here) that there should be a file in that same directory named leaflet.markercluster.js or perhaps leaflet.markercluster.ts (it's Javascript, not TypeScript, so it will be the former). But there is no file named leaflet.markercluster.js in that directory. These are the files in that directory:
leaflet-markercluster.directive.js.map
leaflet-markercluster.directive.metadata.json
leaflet-markercluster.module.d.ts
leaflet-markercluster.module.js
leaflet-markercluster.module.js.map
leaflet-markercluster.module.metadata.json
leaflet-markercluster.directive.d.ts
eaflet-markercluster.directive.js
Which one would that import statement import? If not any of them, where outside this directory would it import that file from? What other information (perhaps in tsconfig.json or angular.json) might affect where this import statement imports from?
the problem in this case was that leaflet.markercluster ALSO needs #types installed. i had to issue a
npm install #types/leaflet #types/leaflet.markercluster
i don't know why the error had nothing to do with #types, but this is in keeping with the soul-crushing nature of Angular development.

Angular2 - require module on client side

In the context of a Node.js / Express / Angular2 / typescript (IDE=Visual Studio) app, I am trying to load a third party .js utility (packery) onto the client side (for use in a directive). Someone made typescript definitions for it. The d.ts file looks like:
declare module "packery" {
interface PackeryOptions { stuff... }
class Packery { stuff .... }
export = Packery;
}
I refer to this d.ts file, tell the browser where the .js packery script lives, and then import the module as such:
import Packery = require('packery');
This compiles without complaint. However, upon running, the browser attempts (and fails) to find "packery" at http://localhost/packery as opposed to knowing packery is an imported library. This is in contrast to the other import statements I have made on the client such as:
import {Http, HTTP_PROVIDERS} from 'angular2/http';
which work - as far as I can tell the only two pieces of information I gave it for those were also a d.ts file and the location of the .js file, just like packery. But, I must be missing something. Have tried many combinations of file locations and linking and can't get it to work. How can I get the proper linking to "packery"?
Thanks!
I found a workaround for this and thought I'd post in case it helps anyone, although I am still having difficulty with the setup posed in the original question, that is, getting statements of the type:
import foo = require('foo')
to run on the CLIENT side. These work for me in node.js on the server, but on the client, for third party libraries that have been loaded via a script tag, I cannot get it to work, even if I add mapping entries to the system.js config file, irrespective of if I point to a .js file or a d.ts file.
Anyway, what does work is if you load the library using the script tag, then in your IDE put a reference path as such at the top of the CLIENT side code
/// <reference path="foo.d.ts" />
and ensure that your d.ts file does not declare a module/namespace but rather exports methods etc. directly. This lets the IDE compile without complaint, and the client side code is able to access the third party library.
However, I'm not sure if it is preferable / best practices to do what I did or if one should be configuring System.js somehow.
Typings are empty definitions of js libraries that aren't written in a typed language. They are only useful in development for IDEs hints and stuff, in your app, you'll still use the library as you normally would, adding the js file in your index.html or w/e you load your js files from.

Substitude one module for another in node.js

If I have a node.js application that has hundreds of files that reference a module (say underscore) and I want to replace that module with another (say lodash) then the obvious way to do this substitution would be a global name replace and switch out the modules in the package.json file.
Is there anyway to just change the module that a name refers to so that when node.js sees require('moduleA') it actually loads 'moduleB' instead? Now I know that this would cause naming hell because anyone working on the project would see require('moduleA') and wouldn't know that the real module being loaded was 'moduleB' so ultimately you'd probably want to go with the first solution. The use case that I'm thinking of is if you want to try a few alternatives for API compatible modules to measure your application's performance (for example) with each module.
If this is an on-going thing and you want to maintain the ability to programmatically switch between the options often, such as in tests:
Instead of using require("underscore"); throughout your codebase, require a local file instead like require("./lib/underscore");, and have that file conditionally re-export underscore or a different library:
if (global.USE_LODASH) {
module.exports = require("lodash");
} else {
module.exports = require("underscore");
}
If this is a one-off thing to try out an alternative library before making the decision to switch, and you want to do this test quickly first without find-and-replacing in all of your files:
Go inside your node_modules folder, delete or rename the underscore folder, and make a symlink named underscore to the replacement module's folder. I don't recommend this as a long-term solution: running npm install again will likely undo this hack, and most projects choose to avoid checking the node_modules folder into their source repository.
Try to use mock-require module.

Categories

Resources