开发者

Loading Javascript through PHP

From a tutorial I read on Sitepoint, I learned that I could load JS files through PHP (it was a comment, anyway). The code for this was in this form:

<script src="js.php?script1=jquery.js&scipt2=main.js" />

The purpose of using PHP was to reduce the number of HTTP requests for JS files. But from the markup above, it seems to me that there are still going to be the same number of requests as if I had written two tags for the JS files (I could be wrong, that's why I'm asking).

The question is how is the PHP code开发者_开发知识库 supposed to be written and what is/are the advantage(s) of this approach over the 'normal' method?


The original poster was presumably meaning that

<script src="js.php?script1=jquery.js&scipt2=main.js" />

Will cause less http requests than

<script src="jquery.js" />
<script src="main.js" />

That is because js.php will read all script names from GET parameters and then print it out to a single file. This means that there's only one roundtrip to the server to get all scripts.

js.php would probably be implemented like this:

<?php
$script1 = $_GET['script1'];
$script2 = $_GET['script2'];

echo file_get_contents($script1); // Load the content of jquery.js and print it to browser
echo file_get_contents($script2); // Load the content of main.js and print it to browser

Note that this may not be an optimal solution if there is a low number of scripts that is required. The main issue is that web browser does not load an infinitely number of scripts in parallel from the same domain.

You will need to implement caching to avoid loading and concatenating all your scripts on every request. Loading and combining all scripts on every request will eat very much CPU.

IMO, the best way to do this is to combine and minify all script files into a big one before deploying your website, and then reference that file. This way, the client just makes one roundtrip to the server, and the server does not have any extra load upon each request.

Please note that the PHP solution provided is by no means a good approach, it's just a simple demonstration of the procedure.


The main advantage of this approach is that there is only a single request between the browser and server.

Once the server receives the request, the PHP script combines the javascript files and spits the results out.

Building a PHP script that simply combines JS files is not at all difficult. You simply include the JS files and send the appropriate content-type header.

When it gets more difficult is based on whether or not you want to worry about caching.

I recommend you check out minify.


<script src="js.php?script1=jquery.js&scipt2=main.js" />

That's:

  • invalid (ampersands have to be encoded)
  • hard to expand (using script[]= would make PHP treat it as an array you can loop over)
  • not HTML compatible (always use <script></script>, never <script />)

The purpose of using PHP was to reduce the number of HTTP requests for JS files. But from the markup above, it seems to me that there are still going to be the same number of requests as if I had written two tags for the JS files (I could be wrong, that's why I'm asking).

You're wrong. The browser makes a single request. The server makes a single response. It just digs around in multiple files to construct it.

The question is how is the PHP code supposed to be written

The steps are listed in this answer

and what is/are the advantage(s) of this approach over the 'normal' method?

You get a single request and response, so you avoid the overhead of making multiple HTTP requests.

You lose the benefits of the generally sane cache control headers that servers send for static files, so you have to set up suitable headers in your script.


You can do this like this:

The concept is quite easy, but you may make it a bit more advanced

Step 1: merging the file

<?php

    $scripts = $_GET['script'];
    $contents = "";
    foreach ($scripts as $script)
    {
         // validate the $script here to prevent inclusion of arbitrary files
         $contents .= file_get_contents($pathto . "/" . $script);
    }

    // post processing here
    // eg. jsmin, google closure, etc.
    echo $contents();

?>

usage:

<script src="js.php?script[]=jquery.js&script[]=otherfile.js" type="text/javascript"></script>

Step 2: caching

<?php
    function cacheScripts($scriptsArray,$outputdir)
    {
       $filename = sha1(join("-",$scripts) . ".js";
       $path = $outputdir . "/" . $filename;
       if (file_exists($path))
       {
            return $filename;
       }
       $contents = "";
       foreach ($scripts as $script)
       {
          // validate the $script here to prevent inclusion of arbitrary files
          $contents .= file_get_contents($pathto . "/" . $script);
        }

       // post processing here
       // eg. jsmin, google closure, etc.
       $filename = sha1(join("-",$scripts) . ".js";
       file_write_contents( , $contents);
       return $filename;
    }
?>

 <script src="/js/<?php echo cacheScripts(array('jquery.js', 'myscript.js'),"/path/to/js/dir"); ?>" type="text/javascript"></script>

This makes it a bit more advanced. Please note, this is semi-pseudo code to explain the concepts. In practice you will need to do more error checking and you need to do some cache invalidation.

To do this is a more managed and automated way, there's assetic (if you may use php 5.3):

https://github.com/kriswallsmith/assetic

(Which more or less does this, but much better)

Assetic Documentation https://github.com/kriswallsmith/assetic/blob/master/README.md

The workflow will be something along the lines of this:

use Assetic\Asset\AssetCollection;
use Assetic\Asset\FileAsset;
use Assetic\Asset\GlobAsset;

$js = new AssetCollection(array(
    new GlobAsset('/path/to/js/*'),
    new FileAsset('/path/to/another.js'),
));

// the code is merged when the asset is dumped
echo $js->dump();

There is a lot of support for many formats:

  • js
  • css
  • lot's of minifiers and optimizers (css,js, png, etc.)
  • Support for sass, http://sass-lang.com/

Explaining everything is a bit outside the scope of this question. But feel free to open a new question!


PHP will simply concatenate the two script files and sends only 1 script with the contents of both files, so you will only have 1 request to the server.


Using this method, there will still be the same number of disk IO requests as if you had not used the PHP method. However, in the case of a web application, disk IO on the server is never the bottle neck, the network is. What this allows you to do is reduce the overhead associated with requesting the file from the server over the network via HTTP. (Reduce the number of messages sent over the network.) The PHP script outputs the concatenation of all of the requested files so you get all of your scripts in one HTTP request operation rather than multiple.


Looking at the parameters it's passing to js.php it can load two javascript files (or any number for that matter) in one request. It would just look at its parameters (script1, script2, scriptN) and load them all in one go as opposed to loading them one by one with your normal script directive.

The PHP file could also do other things like minimizing before outputting. Although it's probably not a good idea to minimize every request on the fly.

The way the PHP code would be written is, it would look at the script parameters and just load the files from a given directory. However, it's important to note that you should check the file type and or location before loading. You don't want allow a people a backdoor where they can read all the files on your server.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜