Define multiple Require.js modules in single JavaScript file - javascript

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

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.

Make pdf.js 1.5 and require.js play nice together

In my project I have long used require.js together with the pdf.js library. Pdf.js have until recently been putting itself on the global object. I could still use it in my requirejs config by using a shim. The pdfjs library will in turn load another library called pdf.worker. In order to find this module the solution was to add a property to the global PDFJS object called workerSrc and point to the file on disk. This could be done before or after loading the pdfjs library.
The pdfjs library uses the pdf.worker to start a WebWorker and to do so it needs the path to a source file.
When I tried to update the pdfjs library in my project to a new version (1.5.314) the way to load and include the library have changed to use UMD modules and now everything get's a bit tricky.
The pdfjs library checks if the environment is using requirejs and so it defines itself as a module named "pdfjs-dist/build/pdf". When this module loads it checks for a module named "pdfjs-dist/build/pdf.worker". Since I have another folder structure I have added them to my requirejs config object with a new path:
paths: {
"pdfjs-dist/build/pdf": "vendor/pdfjs/build/pdf",
"pdfjs-dist/build/pdf.worker": "vendor/pdfjs/build/pdf.worker"
}
This is to make the module loader to find the modules at all. In development this works great. When I try to use the requirejs optimizer in my grunt build step however, it will put all of my project files into one single file. This step will try to include the pdf.worker module as well and this generates an error:
Error: Cannot uglify2 file: vendor/pdfjs/build/pdf.worker.js. Skipping
it. Error is: RangeError: Maximum call stack size exceeded
Since the worker source needs to be in a single file on disk I don't want this module to be included.
So I've tried two different config-settings in the requirejs config.
The first attempt was to override the paths property in my grunt build options:
paths: {
"pdfjs-dist/build/pdf.worker": "empty:"
}
The second thing to test is to exclude it from my module:
modules: [{
name: "core/app",
exclude: [
"pdfjs-dist/build/pdf.worker"
]
}]
Both techniques should tell the optimizer not to include the module but both attempts ended up with the same error as before. The requirejs optimizer still tries to include the module into the build and the attempt to uglify it ends up with a RangeError.
One could argue that since the uglify step fails it will not be included and I can go about my bussiness, but if the uglify step should happen to start working at a new update of pdfjs - what then?
Can anyone help me figure out why the requirejs config won't just exclude it in the build step and how to make it do so.
I found out what the core of my problem was and now I have a way to solve the problem and make my build process to work. My build step in grunt is using grunt-contrib-requirejs and I needed to override some options in the config for this job.
I didn't want the pdf.worker module to be included in my concatenated and minified production code.
I didn't want r.js to minify it only to later exclude it from the concatenated file.
I tried to solve the first problem thinking that it would mean that the second problem also should be solved. When I figured out the two were separate I finally found a solution.
In the r.js example on github there is a property named fileExclusionRegExp. This is what I now use to tell r.js not to copy the file over to the build folder.
fileExclusionRegExp: /pdf.worker.js/
Second, I need to tell the optimizer to not include this module in the concatenated file. This is done by overriding the paths property for this module to the value of "empty:".
paths: {
"pdfjs-dist/build/pdf.worker": "empty:"
}
Now my grunt build step will work without errors and all is well.
Thanks to async5 for informing me about the bug with uglify and the pdf.worker. The workaround is applied in another grunt task that uglify the worker and copies it into the build-folder separately. The options object for the grunt-contrib-uglify task will need this property in order to not break the pdf.worker file:
compress: {
sequences: false
}
Now my project works great when built for production.

Loading specific module from concatenated file using RequireJS

Trying to use the URI.js library in a project, but having trouble with RequireJS. URI's readme indicates that it works with requirejs - which is true when you're using the source - but not when using the minified/concatenated distribution file on its own - as you would in production.
Their build process scoops several libraries into a single .min file, and they all define themselves as modules.
No matter how I require that script, the only argument I receive is the first module in their distribution file (IPv6) which is not what I need.
Is there something trivial I'm missing?
<script>
require.config({
paths: {
urijs: 'dist/URI'
}
});
require(['urijs'], function(URI) {
console.log(URI);
});
</script>
Indeed the minified file cannot be used because it is not correctly built. All the define calls in it are anonymous whereas they should include the module name. If they had, you'd be able to use the minified file.
To get it to work, in the paths configuration, I've put urijs to point to the directory that contains all the individual .js files of the modules, and then I require URI.js as 'urijs/URI'. I let r.js minify it for distribution of my code.
I've installed it with npm but I've just checked with bower and the process should be exactly the same.

Create a module with submodules

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.

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.

Categories