10

Imagine a web app that have dozens of page groups (pg1, pg2, ...) and some of these page groups need some JavaScript code specific only to them, but not to the entire app. For example, some visual fixes on window.resize() might be relevant only in pg2 but nowhere else.

Here are some possible solutions:

1/ Centralized: having one script file for the entire app that deals with all page groups. It's quite easy to know if relevant DOM object is present and so all irrelevant pages simply do a minor extra if(). Biggest advantage is that all JS is loaded once for the entire web app and no modification of the HTML code is needed. Disadvantage is that a additional checks are added to irrelevant pages.

2/ Mixed: the centralized script checks for the existence of a specific function on a page and launches it if it exists. For example we could add a

if (typeof page_specific_resize === 'function') page_specific_resize();

The specific page group in this case will have:

<script>
function page_specific_resize() {
    //....
}
</script>

Advantage is that the code exists only for relevant pages and so isn't tested on every page. Disadvantage is additional size for the HTML results in the entire page group. If there are more than a few lines of code, the page group might be able to load an additional script specific to it but then we're adding an http call there to possibly save a few kilos in the centralized script.

Which is the best practice? Please comment on these solutions or suggest your own solution. Adding some resources to support your claims for what's better (consider performance and ease of maintenance) would be great. The most detailed answer will be selected. Thanks.

Collector
  • 2,034
  • 4
  • 22
  • 39
  • 2
    I prefer the "mixed" solution you gave, but else there is some things to consider : if your several `pg1`, `pg2` don't need a huge amount of JavaScript code, you may probably want to centralize both in order to reduce the number of JavaScript file. This can make the app lighter to debug, because you don't need to navigate through multiple folder to find the proper function associate with the relevant page. The inconvenient is that you will load useless function, which means all the function of `pg1` are loaded for `pg2` too, and for `pg3` also, so it might reduce the speed load of each. – Anwar Sep 01 '15 at 07:52
  • 6
    This is really opinion based and shouldn't be on stackoverflow. – Arnold Daniels Sep 12 '15 at 09:52
  • @Jasny I think the solutions will be beneficial to the community. – jv-k Sep 16 '15 at 20:33

3 Answers3

5

It's a bit tough to think on a best solution since it's an hypothetical scenario and we don't have the numbers to crunch on: what are the most loaded pages, how many are there, the total script size, etc...

That said, I didn't find the specific answer, Best Practice TM, but general points where people agree on.

1) Cacheing:

According to this:

https://developer.yahoo.com/performance/rules.html

"Using external files in the real world generally produces faster pages because the JavaScript and CSS files are cached by the browser"

2) Minification

Still according to the Yahoo link:

"[minification] improves response time performance because the size of the downloaded file is reduced"

3) HTTP Requests

It's best to reduce HTTP calls (based on community answer).

One big javascript file or multiple smaller files?

Best practice to optimize javascript loading

4) Do you need that specific scritp at all?

According to: https://github.com/stevekwan/best-practices/blob/master/javascript/best-practices.md

"JavaScript should be used to decorate your site with additional functionality, and should not be required for your site to be operational."


It depends on the resources you have to load. Depends on how frequently a specific page group is loaded or how much frequently you expect it to be requested. The web app is single page? What each specific script do?

If the script loads a form, the user will not need to visit the page more than once. User will need internet connection to post data later anyway.

But if it's a script to resize a page and the user has some connection hiccups (ex: visiting your web app on a mobile, while taking the the subway), it may be better to have the code already loaded so the user can freely navigate. According to the Github link I posted earlier:

"Events that get fired all the time (for example, resizing/scrolling)"

Is one thing that should be optimized because it's related to performance.

Minifying all the code in one JS file to be cached early will reduce the number of requests made. Also, it may take a few seconds to a connection to stablish, but takes milliseconds to process a bunch of "if" statements.

However, if you have a heavy JS file for just one feature which is not the core of your app (say, this one single file is almost n% the size of the total of other scripts combined), then there is no need to make the user wait for that specific feature.

"If your page is media-heavy, we recommend investigating JavaScript techniques to load media assets only when they are required."

Community
  • 1
  • 1
adrield
  • 629
  • 6
  • 19
4

This is the holy grail of JS and hopefully what modules in ECMA6/7 will solve!

There are module loaders on the client such as JSPM and there are now hot swapping JS code compilers in node.js that can be used on the client with chunks via webpack.

I experimented successfully last year with creating a simple application that only loaded the required chunk of code/file as needed at runtime:

It was a simple test project I called praetor.js on github: github.com/magnumjs/praetor.js

The gh-pages-code branch can show you how it works: https://github.com/magnumjs/praetor.js/tree/gh-pages-code

In the main,js file you can see how this is done with webpackJsonp once compiled:

JS:

 module.exports = {
    getPage: function (name, callback) {
        // no better way to do this with webpack for chunk files ?
        if (name.indexOf("demo") !== -1) {
            require(["./modules/demo/app.js"], function (require) {
                callback(name, require("./modules/demo/app.js"));
            });
        }
 .....

To see it working live, go to http://magnumjs.github.io/praetor.js/ and open the network panel and view the chunks being loaded at runtime when navigating via the select menu on the left.

Hope that helps!

MagJS
  • 422
  • 3
  • 3
1

It is generally better to have fewer HTTP requests, but it depends on your web app.

I usually use requirejs to include the right models and views I need in each file.

While in development it saves me considerable time on debugging (because I know which files are present), in production this could be problematic considering the number of requests.

So I use r.js, which is conceived especially for requirejs, to compile my JS files when it's time for deployment.

Hope this helps

Lyes BEN
  • 990
  • 4
  • 14
  • 1
    Thank you for your answer. Having a single file means that once the first page has loaded, next pages will not make additional requests for JS code, thereby reducing load on the server and making pages load faster. Why did you find requirejs useful? Have u tested loading speeds comparing the methods? Thanks – Collector Sep 14 '15 at 22:03
  • I edited my answer for more clarification – Lyes BEN Sep 15 '15 at 10:54
  • Thanks but you haven't answered the minor questions about your solution that I've introduced in my comment to you. – Collector Sep 18 '15 at 05:37
  • @Collector The idea of reducing server load by having only one JS file is very obscure. Say that you have a JS file for validating forms that you need only in the contact page, why should the user download it if he wont ever get to the contact page? And don't forget that files from require.js are also cached in the browser. – xpy Sep 18 '15 at 08:08
  • If the additional JS code for a rarely used function is very small, say an additional 1k, it's probably easiest to add it to single big file. It'll also ensure that when that function is needed, it'll be there and the user won't have to wait a new connection. All in all, I guess balance between loading times at different scenarios and the overall development effort should be considered. Thanks – Collector Feb 01 '16 at 04:22