0

I am working on a PHP project which writes js files and executes them on page load.

Is it a good practice to write JS file dynamically and append the script tag to the page html and execute it only every page request?

Here is my working creating and linking the JS File:

<?php

if (!function_exists('setScript')) {
    function setScript($script = null)
    {
        static $_script = array();
        if ($script == null) {
            return $_script;
            $_script = array();
        } else {
            $_script[] = $script;
        }
    }
}

if (!function_exists('linkJs')) {
    function linkJs($controllerName, $actionName)
    {
        $jsFileName = randomString(40) . '.js';
        $folderName = PUBLIC_DIR . DS . 'generated';
        if (!is_dir($folderName)) {
            mkdir($folderName);
            chmod($folderName, 777);
        }
        $fileName = $folderName . DS . $jsFileName;
        $availableFiles = scandir($folderName);
        unset($availableFiles[0]);
        unset($availableFiles[1]);
        foreach ($availableFiles as $file) {
            $file = $folderName . DS . $file;
            if (is_file($file)) unlink($file);
        }
        $script = "$(document).ready(function() {\n" . implode("\n", setScript()) . "});";
        file_put_contents($fileName, $script);
        $url = loadClass('Url', 'helpers');
        return "<script type='text/javascript' src='" . $url->baseUrl() . 'public/generated/' . $jsFileName . "'></script>";
    }
}

if (!function_exists('alert')) {
    function alert($message, $returnScript = false)
    {
        if (isAjax()) {
            if ($returnScript) {
                return "\nalert('$message');\n";
            }
            echo "\nalert('$message');\n";
        } else {
            setScript("\nalert('$message');\n");
        }
    }
}

Please suggest if this is a good practice in doing so or any other way i can do it.

Approx 30-40 users would be logged in to the website concurrently and would have approx 5-10 page requests per second. (These are projections. Might go high).

is writing js file (to the hard drive) and linking it is a good practice or just adding the raw scripts to the html body is a good practice since writing to js file gets the js to be un-intrusive.

Also, the javascript generated is going to be dynamic, probably for every page request.

Guns
  • 2,678
  • 2
  • 23
  • 51
  • 1
    well, that depends on how dynamic your scripts are. If they change a lot: yes, that would work. Otherwise I usually put them in separate files which are loaded by the browser and stored in cache. However if the JS changes a lot, that means your cache has to be refreshed each time, which takes even longer than it would inside the page itself. So... it depends on how dynamic your JS is. – Tularis Feb 16 '14 at 12:13
  • yes @Tularis, the scripts are going to be very dynamic – Guns Feb 16 '14 at 12:14
  • 2
    Aside: Instead of `return "alert('$message');";`, you really should use `$json_message = json_encode($message); return "alert($message);";`. – DCoder Feb 16 '14 at 12:16
  • Great @DCoder, didnt think of that... probably that is a good practice to do it. Thanks! – Guns Feb 16 '14 at 12:19
  • 2
    For the main question, since these scripts are so dynamic, writing them to the filesystem and making an extra HTTP request surely causes more overhead than just outputting the script content into the main body. If they're one-time scripts, even more so. – DCoder Feb 16 '14 at 12:20
  • @DCoder, wont the scripts in the html body become intrusive if we look from security POV? I mean anybody can change the script and make things work that they are not suppose to. – Guns Feb 16 '14 at 12:24
  • 2
    No. If people can "make things work that they are not suppose[sic] to" by modifying the JavaScript you send, **your security is already broken**. You must validate the requests sent to your server *on the server* before actually processing them. See also [this question](http://stackoverflow.com/questions/162159/javascript-client-side-vs-server-side-validation). – DCoder Feb 16 '14 at 12:29
  • 2
    By using JS it is already not secure. Don't think about using linking files and such as security as it is not the case. anything client-side can be modified by the client to do as they please. as @DCoder has already said you need to perform checks on the server-side to validate any requests. Also, putting anything in your JS that may lower your security should be carefully thought about. – Michael Coxon Feb 16 '14 at 12:35

1 Answers1

3

If you can see no other choice than dynamically generating every time (my guess is that the content of the script is at least 80% different for each request) then write the script directly into the html file as linking will cause the browser to make another request to include the script.

You are already going to have degraded performance by dynamically generating the file.

The best way of doing this that I can think of is to actually create a php script that generates the js by itself and then create a .htaccess rewrite rule to rewrite /script/generator/{HASH_FOR_REQUEST}.js to /path/to/php-script-generator.php so that you can leverage browser caching if the request is the same.

However, if it is only specific details about the JS that change and the js functions body remains pretty similar (ie, you are using the js to report info back to the client) then consider writing the js in a php file and then using php inline tags to echo the stuff you need to change.

For example:

This script will write an alert to the js so then when loaded with a query string it will report back what is in the query...

<?php
    // disable output buffering 

    /* the reason for this is that the browser will wait 
     * for the first byte returned before continuing with the page. 
     * If it has to wait for the whole file performance will be degarded.
     */

    while(ob_get_level() != 0) ob_end_clean();    

    header("Content-type:text/javascript");

    // it is wise to set some cache headers here


    if(isset($_GET['message']) {
        $message = urldecode($_GET['message']);
    } else {
        $message = "No message!";
    }
?>

// write the js...
alert("<?php echo $message; ?>");

By requesting /path/to/script.php?message=hello+world the script will return alert("hello world");

Michael Coxon
  • 5,311
  • 1
  • 24
  • 51