Create a module with submodules - javascript

I have a small homebrewed framework. I'm using this in several projects and I would like to bring that in a handy format for reusing it.
I would like to organize the code as follows:
Each prototype has its own file
Each file is a require.js module
I would like to combine all files together in one file for shipping.
I have used r.js to combine all files together in one, but how can I load the modules with require(...) from another js-file which is not part of the combined file? Or more detailed, I would like to use the modules from the combined file in another app which has its own modules.
I mean, require.js expects only one module per file and now I have n modules in one file...

What you are describing is what the bundles option is for. Taking an example from the documentation:
bundles: {
'primary': ['main', 'util', 'text', 'text!template.html'],
'secondary': ['text!secondary.html']
}
With this when if you require main from outside the bundle, and main is not yet loaded, then RequireJS will know that it will find the module main in the same place where the module primary is located.

Related

Importing old library which imports its modules

In our company we have a library, that is divided into modules. These modules are in separate files and each of this modules have it's dependencies on other modules. Each module has a definition function, which registers it for other modules to use it later and also it can require other modules in its definition function. The require is similar to angular:
modules.require(['authentication', 'data', 'http'], module => console.log('Here is my module: ', module).
The library has a Synchronizer class, which based on this require in each module, handles importing and providing of the required modules. When a module has not yet been required, it creates a <script> tag, set it's src to the required module file and appends it to the body.
Here is the problem, because if I just import the main file of my library and try to require some module, it appends a <script> tag but the path to the file is not correct, because it is all bundled together by webpack.
Is there a way in webpack, to state, that this folder (folder with the plugin) should remain as is, so that I can then make requests to the individual files in this folder?
I have tried using "import" statement, "require" and also I tried to change the library into npm package, but I am not really allowed to change the library, because it has been tested in this format. So keeping the library as is, would be the best.
For example if I put this library into:
./static/js/mylibrary
then our library can produce for modules.require(['data'], onSuccess) a <script> tag with src like:
./static/js/mylibrary/data.js
Can I setup webpack so that the file stays there? In development? In production?
I am using a project created by vue-cli
As I mentioned in the comment simply putting it to the "public" directory in webpack did the trick for both, development and production. Don't know why I didn't try this before.

How to load a merged JS file containing several modules with requireJs?

That's something I've struggled with for more than a year now, I don't get how we are supposed to load a JS file that contains several AMD modules at once to avoid making as many HTTP requests as there are JS files.
Since we have to define each module separately in the RequireJS config, how is it possible to load only one merged JS file containing all modules at once?
Here is my RequireJS loader: https://gist.github.com/Vadorequest/9553eaf27ac1f469cf63
In that file, what I'd like to merge are:
The requirejs libs (domReady, text, markdown)
The shared source code between the server and the client (Lang, MessageLang... View)
Because these files will increase progressively and increase the number of HTTP calls.
You will have to do this in a build step. Have you consider using RequireJS Optimizer?
The documentation is pretty solid and you will need to add a couple of parameters to your require config:
{
baseUrl: ".",
paths: {
jquery: "some/other/jquery"
},
name: "main",
out: "scripts.js"
}
This will generate one file (scripts.js) with all your files in it. There is also a bundle option if you like to group some files together requirejs bundles
I personally use gulp to take care of my build process so I actually use gulp-requirejs-bundler but the same principles apply.

Concatenate modules in RequireJS

I am using RequireJS to modularize my code. The website I am using will have several distinct page categories. For each one of them I want to load general JS file with all the dependencies that exist across all page categories, jQuery being most obvious one. I have managed to do that already.
For the rest of the pages, I want to have separate JS files. Each page has its own module but I am thinking that it would make more sense if I download several pages modules all at once and this way when the user comes to other pages, he will have the JS file already cached and won't have to download.
For now I tried to concatenate these modules which did work rather well. However, I am not sure how to load the specific module from a file. So far I am doing this:
require(['./js/common'], function (common) {
require(['public']);
});
common is the dependencies file and public is my concatenated file with all the dependencies. Inside it has modules for each page but I don't know how to call a specific one. Any ideas?
Take a look at the bundles option for RequireJS' runtime configuration. In your case it would be something like:
bundles: {
public: ['mod1', 'mod2', ...]
}
I've used mod1, mod2 because I don't see the name of the actual modules in your question but what you'd want there are the names of the modules inside the public bundle and that you want to load individually. With this, RequireJS will know that when you want to load such module, it has to get them from public instead of searching for them indivdually.
Then you should be able to change your loading code to:
require(['./js/common'], function (common) {
require(['mod1']);
});
Again, mod1 is for illustration.
Take a look at require-lazy.
It allows you to bundle independent parts of the application into separate bundles. From the developer's point of view, instead of:
define(["module1", "module2"], function(module1, module2) {...});
you write:
define(["lazy!module1", "lazy!module2"], function(module1, module2) {...});
Modules 1 & 2 will not be loaded upfront; they and their dependencies will be loaded lazilly when you call:
module1.get().then(function(realModule1) {
// here you have access to the real module1
});
Check out the examples for a few use cases.

Define multiple Require.js modules in single JavaScript file

I have two JavaScript modules that I need to use in my web application. And I'm using Require.js to handle my module dependencies. As per Require.js tutorials I've went through, only one module can define in single JavaScript file. Because Require.js keeps those dependencies using the file name.
Eg:
require.config({
paths: {
"jquery": "lib/jquery-latest.min"
}
});
So as far as I know we can define one module per page. I have around 20 modules in my web application. Do I have to create separate JS file for each module ?
Thanks in Advance

How to structure a JavaScript project?

I'm currently working on a big JavaScript project for which we want to define our own API. I'm using RequireJS as my dependency loader and it suits me just fine, allowing me to define modules in their respective file. I do not make use of my own namespace, a module returns an instance, which can be used in other modules, i.e.:
define(
['imported_module'],
function(module){
module.doSomething();
}
)
However as the number of files grows, I'd like to decide how to structure these files in folders. Currently I use the following scheme to name my files:
[projectname].[packagename].[ModuleName]
An example could be stackoverflow.util.HashMap.js. I would like to introduce a project folder, a folder per package and rename the files to the module name, like:
stackoverflow/util/HashMap.js
This structures my code quite neatly into folders, however the filename reflects only the module now. I'd like to define some kind of routing to be able to define how RequireJS should look for files. Example:
The file
stackoverflow/util/stackoverflow.util.HashMap.js
Should be importable by the statement
define(['stackoverflow.util.HashMap'],function(HashMap){});
Has anyone experience with structuring large JavaScript projects and if so, could you share your approach?
You shouldn't specify the routing info on your js file names, those are the namespace and folder paths' jobs. So stackoverflow/util/HashMap.js is just fine. And you can use define("stackoverflow/util/HashMap", ....) to tell the dependency.
If you need to put your modules in a different folders, you can config paths for your loader, see this manual from RequireJS API.
There's no best way for structure your js files. But put the root namespace in a src folder is always a good practice. You can see the dojo source code and YUI source code and use similar ways for your project. They both are large scale Javascript projects.
actually it's better to get js lib routing to load all js using standard interface: "js.yoursite.com/lib-0.2.js" there should be a router (php or other, and able to cache queries). So there you could determine and control whole pathes that you use. Because common jquery plugin should stay at one dir, with jquery, and your own custom plugins not.
And there you control each project by it's own rules:
jquery/
plugins/
jquery.prettyPhoto.js
jquery.min.js
mySuperJS/
stable.0/ -- there your production version for 1.0 branch
module.js
0.1/
module.js
0.2/
module.js
0.3/
module.js
myOtherlib/
stable.0/ -- production version for all 0.* versions
stable.1/ -- production version for all 1.0 versions
0.1/
0.2/
0.3/
0.4/
0.4.1/
0.4.1.18/
We're using such structure around a year and it's the best for us. But sometimes we use more complex solution and separate all modules for libs, plugins, tools, components and apps.

Categories