Jump to content

Recommended Posts

Posted

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!

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
  • Recently Browsing   0 members

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