I honestly don't understand the benefit of RequireJS. If I minify and concatenate all my files using UglifyJS and place the single resulting JS file just before the closing </body> tag, do I still need to use RequireJS? Besides adding 15KB to my page-size, what benefit does RequireJS offer that you cannot get with UglifyJS?
The main point on using requireJs is to have a sane way to modularize your code. Lets say you have an app with some thousand lines of code, you don't want to handle this all in one file. So if you start split it into different files you need a way to load all the single files in the right order. Sure you can create 20 script tags and make sure they are in the right order by yourself, but as your code grows you have to add more script tags and for every file you have to find the right place. This is what requireJs is good for.
Lets say you have a 3 script A.js depends on B.js which depends on C.js
with script tags it would looks like this:
<script src="C.js"></script>
<script src="B.js"></script>
<script src="A.js"></script>
//A.js
console.log('A' + B)
//B.js
B = 'B' + C
//C.js
C = 'C'
})
with requireJs
<script src="require.js" data-main="A.js"></script>
and in every script you declare the dependecies:
//A.js
require(['B.js'], function (B) {
console.log('A' + B)
})
//B.js
define(['C.js'], function (C) {
return 'B' + C
})
//C.js
define([], function () {
return 'C'
})
This is a very simple example but the point is that you don't have to care about the order of your modules as requireJs load the in the right order.
Back to your question the optimizer is more an add on, so if you have a small code base which fits in a single file and is still maintainable, just use uglifyJs. But if you want to split your code in modules requireJs is the way to go.
UglifyJS and RequireJS have very distinct purposes, and both could apply to your situation.
The idea behind RequireJS, and Asynchronous Module Definition in general, is to break your code into smaller chunks, to make it easier to manage. In terms of performance, it has two main benefits:
faster load because you can load multiple chunks in parallel
smaller footprint because you only load the parts of your code that you really need in the current context
A good example is a charting library. Browsers use different standards to render graphics: svg, vml, canvas, etc. A charting library will have code for each of these standards, but at runtime it will only load the part that is relevant to the specific device and browser.
Well, if you use a single file for each page on your site, it would be terrible for code reuse.
You wouldn't want to copy/paste the same code onto each and every page. The files wouldn't be cached, either, which would drastically increase your page load times.
See also: RequireJS's "why" page
With requirejs you can have in JS the same development process you have in other programming languages.
You can write modules, and these modules can be easily reused for other projects, by simply referring their containing file.
Ultimately, when writing for web, requirejs has an optimizer that will uglify and combine the modules together in one script.
Related
I'm trying to figure the most efficient way to structure modules in our website that contains a lot of JavaScript namespaced modules in a single file (app.js) already.
Currently things look a bit like this:
app.js
OURAPP.mapsModule = (function() {
return ...
})();
...
OURAPP.searchModule = (function() {
return ...
})();
..and these are all contained within a single file. So, when we want to use any of these modules we:
search-page.js
...
OURAPP.searchModule.search(query);
...
search.html
...
<script src="js/main.js">
<script src="js/search-page.js">
...
We do have a lot of such modules. However, I'm wondering whether we should be doing something with import/export modules:
Method #2
searchModule.js
export default {
...
}
search-page.js
import searchModule from "./js/searchModule";
...
searchModule.search(query);
...
I'm guessing that a single file namespaced modules will be faster for the page to load(?) as it's only a single file to download. But when I'm looking at testing frameworks (e.g. Jest) they give many examples where module script files are loaded in this manner. Does it lend itself better to testing I'm wondering? Personally, I prefer this structure anyway but it's a bold change of direction from how the site has been built up until now and I'll need to good reason to suggest this. This website's is pretty much all generated server-side with JavaScript just doing the show/hide, query APIs, etc, with the addition on scrips and JavaScript libraries such as jQuery, Bootstrap, Isotope when required on each page.
I've read around but can't find anything comparing exactly both methods here and reasons for and against either. Would appreciate any suggestions or helpful advice, thanks.
Don't default-export objects, use named exports instead:
// searchModule.js
export function search(…) {
…
}
// search-page.js
import * as searchModule from "./js/searchModule";
…
searchModule.search(query);
…
I'm guessing that a single file namespaced modules will be faster for the page to load as it's only a single file to download.
Yes, that's true. However, do not let that affect your decision on how to structure your modules. You should always modularise your code so that it is the cleanest possible. Put the maps stuff in a different module than the search stuff.
You will then use a bundler or packer tool to create a single minified JS file to download that contains all the modules that the respective page needs.
Including many javascript files on the same page can lead to low performance.
What I want to ask is:
Is it best to keep separate files or include all files in one javascript file?
And if it is better to include everything in the same file Javascript, how can I avoid conflicts between different scripts?
It is best to keep separate files or include all files in one file Javascript?
To avoid multiple server requests, it is better to group all your JavaScript files into only one.
If you're using C#.Net + ASP.Net, you can bundle your files — it is a very good way to compress your scripts.
how can I avoid conflicts between different scripts?
You can use RequireJS; different names it is a good idea too; and every time that a plug-in/script ends, use ; to determine its end.
Performatic consideration
To maintain the productivity of your scripts, you should minify them.
Solution for a single page application
After you have minified your scripts, then group them all — regardless if they are plugins or your own code — into a single file and call it in your application.
Solution for a multiple page application
In this case, you should call just the necessary JavaScript for each page. How can you do this?
After you minified all of your scripts, then separate them in categories. Take a look to get the idea:
/assets/js/core.js — here you put your JavaScript code that is necessary to all of your pages. It is your core; your kernel;
/assets/js/plugins.js — here you put all the plugins that runs with all of your pages (i.e. jquery, backbone, knockout, and so on.);
/assets/js/home/bootstrap.js — here is the magic: in this file you have to fill with the code that your home will call;
/assets/js/contact/bootstrap.js — the same as before: this file you should to place with the code that your contact page will call.
HINT: core.js and plugins.js can occupy the same file when you deploy your application. To better comprehension and developing, it is good to maintain them into separated files.
Third party plugins
To give you an idea, the file of your plugins should be like this:
/* PlaceHolder plugin | http://www.placeholderjs.com/ | by #phowner */
; $(function(){ /* the placeholder's plugin goes here. */ });
/* Masked Inputs plugin | http://www.maskedjs.com/ | by #maskedowner */
; $(function(){ /* the masked input's plugin goes here. */ });
/* Mousewheel plugin | http://www.mousewheeljs.com/ | by #mousewheelowner */
; $(function(){ /* the mousewheel's plugin goes here. */ });
Serving one large single vs serving multiple small files depends on quite a few factors:
do all clients require the exact same code base?
i.e. we probably don't need shim for modern browsers, so why serve it?
do we change those files regularly?
caching files that don't change often can be used to reduce traffic
do we want to use CDNs?
serving jQuery from New York to New York rather than shoving it around half the planet probably ammortizes an additional HTTP request (performance-wise at least)
Conflicts can be reduced/eliminated by introducing your own scope for each script. A common way is to use IIFEs/SIAFs and inject required variables.
A quick and simple example of an IIFE:
(function () { // IIFE
var undefined = true;
})();
if (document.querySelectorAll === undefined) {
// polyfill
}
If the content in the IIFE would execute in global scope, it would probably crash your polyfill. Since it is executed in a local (function) scope, you are pretty much safe from conflicts.
Note: usually, your polyfill should not be implemented in global scope as well.
Conflicting code has nothing to do with combining JavaScript or put it in separate files but it requires descent programming.
To combine or not to combine depends on multiple things like:
file size
how many changes are you expecting.
How many relevant code has to be loaded at once that it is useful to
put it in one file or separate files
one file keeps the number of file requests low
..
It's generally better to bundle. If you are using Visual Studio you can use the Web Essentials bundling for JS, CSS, and even image sprites.
http://vswebessentials.com/features/bundling
sorry for beeing a little lazy and not trying it all out myself, but I thought a nice answer on Stackoverflow might help some other guys too. I'm pondering whether or not to use requireJS to load my modules. Currently I'm doing that on my very own, so I have some questions about requireJS.
How does requireJS deal with multiple references (does it cache files/modules) ?
More precisely, if you have calls like require(["some/module", "a.js", "b.js"], function...}); and you again reference a.js or b.js in later .require or .define calls, how does requireJS handle those? My guess is, it will entirely ignore those additional references, is that correct? If so, is it possible to force requireJS to reload a script ?
Does requireJS always transfer files over the wire or you can load modules statically ?
What I normally do is, to concatenate all of my js files (modules included), except for those which need to get loaded dependent on run-time conditions. As far as I read the requireJS doc, you can define own names for modules. So my question is, can you load a module which is already present in the script, without transferring it over the wire ?
As far as I understood the doc, names are created automatically for modules, based on their path location and filename, so this would make no sense for my requirement here.
requirejs.undef() should do the trick
Normally, a module will only be loaded once by require.js. require.js will always resolve dependencies and load the modules in the right order so that you don't have to care about that. Subsequent calls to require for the same module will yield it immediately.
It is not possible to reload a module. If you really have a need for loading the same module more than once (which would unfortunately indicate that there is something wrong with your module's design) you can have a look at the Multiversion support.
I am not sure I understand what you mean by "load modules statically". But if I am guessing right you want to load several modules as one and use them seperately. This is possible:
Typically in your modules you will be doing something like:
define(['moduleA', 'moduleB', 'moduleC'], function (a, b, c) {
...
return exports;
});
where exports can be more or less anything, a function, an object, whatever. So you can also do something like:
define(['moduleA', 'moduleB', 'moduleC'], function (a, b, c) {
...
return {moduleA: a, moduleB: b, moduleC: c};
});
exporting them all together.
Note however that you should really have a look at the optimization tool. It can group related modules together.
Finally, the automatic naming is a misunderstanding, you can be explicit on the names of your modules.
I've been reading about the module pattern, but everything I read assumes that the entire contents of the module will be in a single file. I want to have one file per class.
I've resorted to doing this at the top of every file:
if(window.ModuleName === undefined) { window.ModuleName = {}; }
ModuleName.ClassName = function () { ... }
But this allows files to be included without their dependencies, which is also annoying. For example, lets say there is ClassA which uses ClassB, and "ClassB.js" is left out of the HTML, then ClassA will throw up errors. As far as I'm aware Javascript lacks an import statement, so in this case I actually want everything to be in a single file.
I assume that large javascript projects are broken up into multiple files, so there has to be a way around this. How is it generally done? Is there some tool that will combine multiple class files into a single module file?
This is a big topic but let me explain as much as I can. Javascript requires that you have preloaded anything you intended to use, which is why your module pattern has all the "things" in the same file. But if you plan to separate them in different files then you have to manage it before using. I suggest the following approaches
Concatenate them before serving them in the server. For example in jsp, you can create a servlet that returns contenttype = "text/javascript", inside that servlet you can append all the scripts you need in one dynamically generated script then return it to the client.
In your ant or maven builds etc, there are configurations where in you can concatenate them the files you want together. This is a common practice therefore you should find many reference in the internet.
Lazy-load javascripts. This is my preferred way. I use Lazyload javascript library. Basically I declare the dependencies of certain codes much like "import" in Java, then before i call any of them i load their dependencies. This allows for optimized dependency loading without scripts redundancies. The problem is you need to write some fairly complicated scripts to do this.
Hope to help.
In complex client side projects, the number of Javascript files can get very large. However, for performance reasons it's good to concatenate these files, and compress the resulting file for sending over the wire. I am having problems in concatenating these as the dependencies are included after they are needed in some cases.
For instance, there are 2 files:
/modules/Module.js <requires Core.js>
/modules/core/Core.js
The directories are recursively traversed, and Module.js gets included before Core.js, which causes errors. This is just a simple example where dependencies could span across directories, and there could be other complex cases. There are no circular dependencies though.
The Javascript structure I follow is similar to Java packages, where each file defines a single Object (I'm using MooTools, but that's irrelevant). The structure of each javascript file and the dependencies is always consistent:
Module.js
var Module = new Class({
Implements: Core,
...
});
Core.js
var Core = new Class({
...
});
What practices do you usually follow to handle dependencies in projects where the number of Javascript files is huge, and there are inter-file dependencies?
Using directories is clever, however, I think you might run into problems when you have multiple dependencies. I found that I had to create my own solution to handle this. So, I created a dependency management tool that is worth checking out. (Pyramid Dependency Manager documentation)
It does some important things other javascript dependency managers don't do, mainly
Handles other files (including inserting html for views...yes, you can separate your views during development)
Combines the files for you in javascript when you are ready for release (no need to install external tools)
Has a generic include for all html pages. You only have to update one file when a dependency gets added, removed, renamed, etc
Some sample code to show how it works during development.
File: dependencyLoader.js
//Set up file dependencies
Pyramid.newDependency({
name: 'standard',
files: [
'standardResources/jquery.1.6.1.min.js'
]
});
Pyramid.newDependency({
name:'lookAndFeel',
files: [
'styles.css',
'customStyles.css'
]
});
Pyramid.newDependency({
name:'main',
files: [
'createNamespace.js',
'views/buttonView.view', //contains just html code for a jquery.tmpl template
'models/person.js',
'init.js'
],
dependencies: ['standard','lookAndFeel']
});
Html Files
<head>
<script src="standardResources/pyramid-1.0.1.js"></script>
<script src="dependencyLoader.js"></script>
<script type="text/javascript">
Pyramid.load('main');
</script>
</head>
This may be crude, but what I do is keep my separate script fragments in separate files. My project is such that I'm willing to have all my Javascript available for every page (because, after all, it'll be cached, and I'm not noticing performance problems from the parse step). Therefore, at build time, my Ant script runs Freemarker via a little custom Ant task. That tasks roots around the source tree and gathers up all the separate Javascript source files into a group of Maps. There are a few different kinds of sources (jQuery extensions, some page-load operations, so general utilities, and so on), so the task groups those different kinds together (getting its hints as to what's what from the script source directory structure.
Once it's built the Maps, it feeds those into Freemarker. There's a single global template, and via Freemarker all the script fragments are packed into that one file. Then that goes through YUI compressor, and bingo! each page just grabs that one script, and once it's cached there's no more script fetchery over my entire site.
Dependencies, you ask? Well, that Ant task orders my source files by name as it builds those maps, so where I need to ensure definition-use ordering I just prefix the files with numeric codes. (At some point I'm going to spiff it up so that the source files can keep their ordering info, or maybe even explicitly declared dependencies, inside the source in comment blocks or something. I'm not too motivated because though it's a little ugly it really doesn't bother anybody that much.)
There is a very crude dependency finder that I've written based on which I am doing the concatenation. Turns out the fact that its using MooTools is not so irrelevant after all. The solution works great because it does not require maintaining dependency information separately, since it's available within the javascript files itself meaning I can be super lazy.
Since the class and file naming was consistent, class Something will always have the filename Something.js. To find the external dependencies, I'm looking for three things:
does it Implement any other
classes
does it Extend any other
classes
does it instantiate other classes
using the new keyword
A search for the above three patterns in each javascript file gives its dependent classes. After finding the dependent classes, all Javascript files residing in any folder are searched and matched with this class name to figure out where that class is defined. Once the dependencies are found, I build a dependency graph and use the topological sort algorithm to generate the order in which files should be included.
I say just copy and paste this files to a one file in an ordered way. Each file will have a starting and ending comment to distinguish each particular code.
Each time you updated one of the files, you'll need to updated this file. So, this file need to contain only finish libraries, that not going to changes in the near time.
Your directory structure is inverted...
Core dependencies should be in the root and modules are in subdirs.
scripts/core.js
scripts/modules/module1.js
and your problem is solved.
Any further dependency issues will be indicative of defective 'class'/dependency design.
Similar to Mendy, but I create combined files on server-side. The created files will also be minified, and will have a unique name to omit cache issues after an update.
Of course, this practice only makes sense in a whole application or in a framework.
I think your best bet if at all possible, would be to redesign to not have a huge number of javascript files with interfile dependencies. Javascript just wasn't intended to go there.
This is probably too obvious but have you looked at the mootools Core Depender: http://mootools.net/docs/more/Core/Depender
One way to break the parse-time or load-time dependencies is with Self-Defining Objects (a variation on Self-Defining Functions).
Let's say you have something like this:
var obj = new Obj();
Where this line is in someFile.js and Obj is defined in Obj.js. In order for this to parse successfully you must load or concatenate Obj.js before someFile.js.
But if you define obj like this:
var obj = {
init: function() {
obj = new Obj();
}
};
Then at parse or load time it doesn't matter what order you load the two files in as long as Obj is visible at run-time. You will have to call obj.init() in order to get your object into the state you want it, but that's a small price to pay for breaking the dependency.
Just to make it clearer how this works here is some code you can cut and paste into a browser console:
var Obj = function() {
this.func1 = function ( ) {
console.log("func1 in constructor function");
};
this.init = function () {
console.log("init in constructor function");
}
};
var obj = {
init: function() {
console.log("init in original object");
obj = new Obj();
obj.init();
}
};
obj.init();
obj.func1();
And you could also try a module loader like RequireJS.