Jump to content

Combine JS Files


Boost
 Share

Recommended Posts

And here is the same thing, but for JS files. The implementation is straightforward; you only need to add one PHP file to your server and make a few tweaks. The main difference is that this script does not minify the files. During my tests, minifying the JS files didn't work well for me.

My setup:
-site/
  -templates/
    - inc/
    - scripts/
    

_init.php
Include the CombinedJS.php file at the top of my _init.php:

include_once('./inc/CombinedJS.php');

_main.php
Add the following to the <head> section:

<?php 
	$jsFiles = [
	   	paths()->templates . 'scripts/uikit.min.js',
	   	paths()->templates . 'scripts/uikit-icons.min.js',
	];
		
	echo CombinedJS::JS($jsFiles);
?>

CombinedJS.php

<?php namespace ProcessWire;

use RuntimeException;

/**
 * Class CombinedJS
 *
 * A class for combining JavaScript files and generating a script tag for the combined JavaScript.
 */
class CombinedJS {

    /**
     * @var string|null The output directory for saving the combined JavaScript file.
     */
    private static $outputDirectory;

    /**
     * @var string|null Hash of the concatenated content of JavaScript files.
     */
    private static $filesHash;

    /**
     * Initializes the output directory if it is not already set.
     */
    private static function initOutputDirectory() {
        if (!isset(self::$outputDirectory)) {
            self::$outputDirectory = paths()->templates . 'scripts/';
        }
    }

    /**
     * Checks if a directory is writable.
     *
     * @param string $directory The directory path to check.
     *
     * @return bool True if the directory is writable, false otherwise.
     */
    private static function isWritableDirectory($directory) {
        // Check if the directory exists
        if (!is_dir($directory)) {
            return false;
        }

        // Check if the directory is writable
        if (!is_writable($directory)) {
            return false;
        }

        return true;
    }

    /**
     * Combines JavaScript files without minifying them.
     *
     * @param array $files An array of JavaScript file paths.
     *
     * @return string The combined JavaScript content.
     */
    private static function combineJS(array $files): string {
        $combinedJS = '';

        foreach ($files as $file) {
            // Read the content of each JavaScript file
            $jsContent = file_get_contents($file);

            // Append the JavaScript content to the combined JavaScript content
            $combinedJS .= $jsContent;
        }

        return $combinedJS;
    }

    /**
     * Generates a unique filename for the combined JavaScript file based on the provided file paths.
     *
     * @param array $files An array of JavaScript file paths.
     *
     * @return string The generated combined JavaScript filename.
     */
    private static function generateCombinedFilename(array $files): string {
        return md5(implode('', $files)) . '.js';
    }

    /**
     * Saves the combined JavaScript content to a file.
     *
     * @param string $filename The filename for the combined JavaScript file.
     * @param string $content The combined JavaScript content to be saved.
     *
     * @throws RuntimeException If there is an error writing the file to disk.
     */
    private static function saveToFile(string $filename, string $content): void {
        // Save the combined JavaScript content to the specified file
        $filePath = self::$outputDirectory . DIRECTORY_SEPARATOR . $filename;

        if (file_put_contents($filePath, $content) === false) {
            $error = error_get_last();
            $errorMessage = isset($error['message']) ? $error['message'] : 'Unknown error';
            throw new RuntimeException('Failed to write the combined JavaScript file to disk. Error: ' . $errorMessage);
        }
    }

    /**
     * Generates a script tag for the combined JavaScript file based on the provided file paths.
     *
     * @param array $files An array of JavaScript file paths.
     *
     * @return string The script tag for the combined JavaScript file.
     *
     * @throws RuntimeException If the output directory is not writable.
     */
    public static function JS(array $files): string {
        // Initialize the output directory
        self::initOutputDirectory();

        // Ensure the output directory is writable
        if (!self::isWritableDirectory(self::$outputDirectory)) {
            throw new RuntimeException('The output directory is not writable.');
        }

        // Combine JavaScript files without minifying
        $combinedJS = self::combineJS($files);

        // Generate a unique filename for the combined JavaScript file
        $combinedFilename = self::generateCombinedFilename($files);

        // Save the combined JavaScript content to a file
        self::saveToFile($combinedFilename, $combinedJS);

        // Return the script tag
        return '<script src="' . urls()->templates . 'scripts/' . $combinedFilename . '"></script>';
    }

}

Notes:

  • Ensure that you have writing permissions for the $outputDirectory location.
  • The combined JS file will be generated and saved only if the files have changed or if the file doesn't exist on disk.
  • The order of the combined file will adhere to the sequence specified in the array.
  • Modify the hardcoded paths based on your requirements.

Any suggestions for improvements are welcome!

Cheers!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...