How To Minify Js In Php Easily...or Something Else
Solution 1:
I have used a PHP implementation of JSMin by Douglas Crockford for quite some time. It can be a little risky when concatenating files, as there may be a missing semicolon on the end of a closure.
It'd be a wise idea to cache the minified output and echo what is cached so long as it's newer than the source file.
require'jsmin.php';
if(filemtime('scripts_template.js') < filemtime('scripts_template.min.js')) {
read_file('scripts_template.min.js');
} else {
$output = JSMin::minify(file_get_contents('scripts_template.js'));
file_put_contents('scripts_template.min.js', $output);
echo$output;
}
You could also try JShrink. I haven't ever used it before, since I haven't had difficulty with JSMin before, but this code below should do the trick. I hadn't realized this, but JShrink requires PHP 5.3 and namespaces.
require'JShrink/Minifier.php';
if(filemtime('scripts_template.js') < filemtime('scripts_template.min.js')) {
read_file('scripts_template.min.js');
} else {
$output = \JShrink\Minifier::minify(file_get_contents('scripts_template.js'));
file_put_contents('scripts_template.min.js', $output);
echo$output;
}
Solution 2:
Take a look at Assetic, a great asset management library in PHP. It is well integrated with Symfony2 and widely used.
Solution 3:
Depending on the restrictions of your server (eg, not running in safe mode), perhaps you can also look beyond PHP for a minifier and run it using shell_exec()
. For instance, if you can run Java on your server, put a copy of YUI Compressor on the server and use it directly.
Then scripts.php would be something like:
<?php$cmd = "java -cp [path-to-yui-dir] -jar [path-to-yuicompressor.jar] [path-to-scripts_template.js]";
echo(shell_exec($cmd));
?>
Other suggestion: build the minification step into your development workflow, before you deploy to the server. For example I set up my Eclipse PHP projects to compress JS and CSS files into a "build" folder. Works like a charm.
Solution 4:
Using "PHPWee": https://github.com/searchturbine/phpwee-php-minifier
(which also uses JSmin
), I pushed @Robert K solution a little bit further.
This solution allows minifying both CSS and JS files. If the non-minified file cannot be found, it will return an empty string. If the minified file is older than the non-minified, it will try to create it. It will create a sub-folder for the minified file if it doesn't exist. If the method can minify the file successfully, it returns it either in a <script>
(javascript) or a <link>
(CSS) tag. Otherwise, the method will return the non-minified version in the proper tag.
Note: tested with PHP 7.0.13
/**
* Try to minify the JS/CSS file. If we are not able to minify,
* returns the path of the full file (if it exists).
*
* @param $matches Array
* 0 = Full partial path
* 1 = Path without the file
* 2 = File name and extension
*
* @param $fileType Boolean
* FALSE: css file.
* TRUE: js file
*
* @return String
*/privatestaticfunctioncreateMinifiedFile(array$matches, bool$fileType)
{
if (strpos($matches[1], 'shared_code') !== false) {
$path = realpath(dirname(__FILE__)) . str_replace(
'shared_code',
'..',
$matches[1]
);
} else {
$path = realpath(dirname(__FILE__)) .
"/../../" . $matches[1];
}
if (is_file($path . $matches[2])) {
$filePath = $link = $matches[0];
$min = 'min/' . str_replace(
'.',
'.min.',
$matches[2]
);
if (!is_file($path . $min) or
filemtime($path . $matches[2]) >
filemtime($path . $min)
) {
if (!is_dir($path . 'min')) {
mkdir($path . 'min');
}
if ($fileType) { // JS$minified = preg_replace(
array(
'/(\))\R({)/',
'/(})\R/'
),
array(
'$1$2',
'$1'
),
Minify::js(
(string) file_get_contents(
$path . $matches[2]
)
)
);
} else { // CSS$minified = preg_replace(
'@/\*(?:[\r\s\S](?!\*/))+\R?\*/@', //deal with multiline comments'',
Minify::css(
(string) file_get_contents(
$path . $matches[2]
)
)
);
}
if (!empty($minified) and file_put_contents(
$path . $min,
$minified
)
) {
$filePath = $matches[1] . $min;
}
} else { // up-to-date$filePath = $matches[1] . $min;
}
} else { // full file doesn't exists$filePath = "";
}
return$filePath;
}
/**
* Return the minified version of a CSS file (must end with the .css extension).
* If the minified version of the file is older than the full CSS file,
* the CSS file will be shrunk.
*
* Note: An empty string will be return if the CSS file doesn't exist.
*
* Note 2: If the file exists, but the minified file cannot be created,
* we will return the path of the full file.
*
* @link https://github.com/searchturbine/phpwee-php-minifier Source
*
* @param $path String name or full path to reach the CSS file.
* If only the file name is specified, we assume that you refer to the shared path.
*
* @return String
*/publicstaticfunctiongetCSSMin(String$path)
{
$link = "";
$matches = array();
if (preg_match(
'@^(/[\w-]+/view/css/)?([\w-]+\.css)$@',
$path,
$matches
)
) {
if (empty($matches[1])) { // use the default path$matches[1] = self::getCssPath();
$matches[0] = $matches[1] . $matches[2];
}
$link = self::createMinifiedFile($matches, false);
} else {
$link = "";
}
return (empty($link) ?
'' :
'<link href="' . $link . '">'
);
}
/**
* Return the path to fetch CSS sheets.
*
* @return String
*/publicstaticfunctiongetCssPath()
{
return'/shared_code/css/' . self::getCurrentCSS() . "/";
}
/**
* Return the minified version of a JS file (must end with the .css extension).
* If the minified version of the file is older than the full JS file,
* the JS file will be shrunk.
*
* Note: An empty string will be return if the JS file doesn't exist.
*
* Note 2: If the file exists, but the minified file cannot be created,
* we will return the path of the full file.
*
* @link https://github.com/searchturbine/phpwee-php-minifier Source
*
* @param $path String name or full path to reach the js file.
*
* @return String
*/publicstaticfunctiongetJSMin(String$path)
{
$matches = array();
if (preg_match(
'@^(/[\w-]+(?:/view)?/js/)([\w-]+\.js)$@',
$path,
$matches
)
) {
$script = self::createMinifiedFile($matches, true);
} else {
$script = "";
}
return (empty($script) ?
'' :
'<script src="' . $script . '"></script>'
);
}
In a (Smarty) template, you might use those methods like this:
{$PageController->getCSSMin("main_frame.css")}
//Output: <link href="/shared_code/css/default/min/main_frame.min.css">
{$PageController->getCSSMin("/gem-mechanic/view/css/gem_mechanic.css")}
//Output: <link href="/gem-mechanic/view/css/min/gem_mechanic.min.css">
{$PageController->getJSMin("/shared_code/js/control_utilities.js")}
//Output: <script src="/shared_code/js/min/control_utilities.min.js"></script>
{$PageController->getJSMin("/PC_administration_interface/view/js/error_log.js")}
//Output: <script src="/PC_administration_interface/view/js/min/error_log.min.js"></script>
Unit tests:
/**
* Test that we can minify CSS files successfully.
*/publicfunctiontestGetCSSMin()
{
//invalid style$this->assertEmpty(
PageController::getCSSMin('doh!!!')
);
//shared style$path = realpath(dirname(__FILE__)) . '/../css/default/min/main_frame.min.css';
if (is_file($path)) {
unlink ($path);
}
$link = PageController::getCSSMin("main_frame.css");
$this->assertNotEmpty($link);
$this->assertEquals(
'<link href="/shared_code/css/default/min/main_frame.min.css">',
$link
);
$this->validateMinifiedFile($path);
//project style$path = realpath(dirname(__FILE__)) . '/../../gem-mechanic/view/css/min/gem_mechanic.min.css';
if (is_file($path)) {
unlink ($path);
}
$link = PageController::getCSSMin("/gem-mechanic/view/css/gem_mechanic.css");
$this->assertNotEmpty($link);
$this->assertEquals(
'<link href="/gem-mechanic/view/css/min/gem_mechanic.min.css">',
$link
);
$this->validateMinifiedFile($path);
}
/**
* Test that we can minify JS files successfully.
*/publicfunctiontestGetJSMin()
{
//invalid script$this->assertEmpty(
PageController::getJSMin('doh!!!')
);
//shared script$path = realpath(dirname(__FILE__)) . '/../js/min/control_utilities.min.js';
if (is_file($path)) {
unlink ($path);
}
$script = PageController::getJSMin("/shared_code/js/control_utilities.js");
$this->assertNotEmpty($script);
$this->assertEquals(
'<script src="/shared_code/js/min/control_utilities.min.js"></script>',
$script
);
$this->validateMinifiedFile($path);
//project script$path = realpath(dirname(__FILE__)) . '/../../PC_administration_interface/view/js/min/error_log.min.js';
if (is_file($path)) {
unlink ($path);
}
$script = PageController::getJSMin("/PC_administration_interface/view/js/error_log.js");
$this->assertNotEmpty($script);
$this->assertEquals(
'<script src="/PC_administration_interface/view/js/min/error_log.min.js"></script>',
$script
);
$this->validateMinifiedFile($path);
}
/**
* Make sure that the minified file exists and that its content is valid.
*
* @param $path String the path to reach the file
*/privatefunctionvalidateMinifiedFile(string$path)
{
$this->assertFileExists($path);
$content = (string) file_get_contents($path);
$this->assertNotEmpty($content);
$this->assertNotContains('/*', $content);
$this->assertEquals(
0,
preg_match(
'/\R/',
$content
)
);
}
Additional notes:
- In
phpwee.php
I had to replace<?
by<?php
. - I had problems with the namespace (the function
class_exists()
was not able to find the classes even though they were in the same file). I solved this problem by removing the namespace in every file.
Solution 5:
JavaScriptPacker works since 2008, and is quite simple
Post a Comment for "How To Minify Js In Php Easily...or Something Else"