📜 ⬆️ ⬇️

Combining javascript files

The era of the warm tube WEB 1.0 has passed long ago, and recently we are dealing with pages that are teeming with so-called dynamism. Dynamism can be provided with the help of JavaScript, VbScript and plug-ins like Java, Flash, Silverlight. In this article I want to touch on one of the possible optimizations of the web site - combining all javascript files into one.

What for?


There are two main reasons:
  1. Increase page loading speed.
  2. Reducing server load.

Let's start with the "increase download speed." Often the website is full of scripts and their total number can exceed 50. However, this will already be a “clinical case.” But at least 15-30 is found regularly. For each script, the browser sends a request and, depending on the response, either loads it completely or takes it from the cache. 15 requests is a lot. It takes time. Yes, all modern browsers download files in parallel, but this is not a reason to exploit them in this way. In my case, the page loading speed increased several times.

Regarding reducing the load on the server - everything is more complicated. The decrease in the number of requests improves the situation anyway, but I find it difficult to say how much, because I'm not admin I believe that to reduce the load you can find a lot of simpler and more effective solutions. Perhaps this is the so-called saving of matches against the background of a fire. But as a side effect - amiss.
')

How?


I believe that there are only two main ways:

In the first case, we get rid of the hated by many eval-a, but force the browser to compile unused code. In the second case, we use eval, forcing the browser to compile a part of the already compiled file. It looks like this:

//  . window.__js = { 'engine': function(){ /*  */ }, 'some': function(){ /*  */ } }; //  window.__js = { 'engine': '/*  */', 'some': '/*  */' }; 

But I had no choice, because the engine used is teeming with a “doubtful quality” code. I cannot wrap this code in an anonymous function, because:

 //  1 function some(){ ... } //  2 some(); 

If we wrap both files in anonymous functions and then execute them, we get an error - the browser will not be able to find some. The reason lies in the fact that the resulting code:

 function(){ function some(){ ... }; } 

Does not lead to window.some! == undefined; The some function is defined in the scope of an anonymous function, not a window at all, as it would be if it were defined in a separate file. The solution to this problem was found in jQuery. The fact is that you can execute javascript code in the global scope using:

 ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); 

Depending on the browser, we call either execScript, or run our usual eval, setting it to this window. This approach has been used in jQuery since version 1.6. In earlier versions, a script tag was created in which the necessary code was placed, and this script was attached to the document.

Compression and obfuscation


In parallel with the assembly of all the files in the list, we can make fun of them. Firstly, they can be compressed, secondly, they can ruin their readability. To do this, you can use YUI Compressor or any equivalent. In the end, we get slightly less code without formatting (indents, extra spaces, shortened names of local variables, etc.) compressed into one line.

Layout


The easiest part of the task. The algorithm is as simple as boots:

An example of what should happen in the end can be found here . You can activate this algorithm either manually or when loading each page.

Debugging


The life of a programmer would be wonderful if it were not for the numerous bugs that have the habit of appearing at the wrong time and hiding well. Here our and you idea fails on all fronts. Our code is unreadable, the firebug hangs on it, and errors indicate where it goes. In addition, most variables are of the form a, b, c. Chrome comes to the rescue. The fact is that he is able to “de-obfuscate” the code to a quite readable state (context menu in the Scripts tab). For example:

 function oa(a) { var b = 1, c = 0, d; if (!D(a)) { b = 0; for (d = a[s] - 1; d >= 0; d--) c = a.charCodeAt(d), b = (b << 6 & 268435455) + c + (c << 14), c = b & 266338304, b = c != 0 ? b ^ c >> 21 : b; } return b; } 

The result is very far from the original, but this can already be at least read. Unfortunately, there are some problems with setting breakpoints and triggering them. But bezrybe and cancer fish. You can live.

Final touch


If we add the / * // @ sourceURL = # {name} * / construct to the end of the code that will be passed through eval, the chrome will show us the specified # {name} in the list of scripts. Unfortunately, this mechanism did not work for me in Firefox. I needed a wrapper comment for IE.



Used


Working locally with a “single file” is pretty damn inconvenient, so you can write something like this bike:

 window.__js_ready = {}; function __include( name ) { //       if( !__js_ready[ name ] ) { __js_ready[ name ] = true; //   if( ONLINE ) // "" { ( window.execScript || function( data ) { window[ "eval" ].call( window, __js[ name ] ); } )( data ); } else //  { //      ,  //  document.write } } } 

 //  html  <script type="text/javascript"> __include( 'engine' ); </script> <script type="text/javascript"> //  "engine" </script> 

Of course, there are many options for implementing a script connection. Yes, and this can be improved. For example, putting the site engine on the "event basis". Those. execute any code only when a number of conditions have been met, for example: all the required modules have been loaded.

Minuses


Source: https://habr.com/ru/post/130276/


All Articles