jsmin as a PHP extension – JavaScript Minify the Fast Way
Yahoo’s performance docs and Google’s page speed best practices recommend that both external and inline javascript code is minified. Two popular tools for minifying JavaScript are JSMIN and YUI Compressor.
I needed to have an efficient solution that can minify javascript on the fly. Unfortunately these tools do not work because a process would need to be forked every time minification needed to be performed. In PHP, one possible solution is to use jsmin-php, but again this is a very slow option. jsmin-php is written in PHP code and parsing a JavaScript file in PHP is relatively slow.
So I decided to develop a php extension based on jsmin.c developed by Douglas Crockford. It creates a native PHP function included as a PHP extension (written in C as opposed to PHP). The speed and efficiency improvement over jsmin-php is over 25x!
Try it out!
Get it here
Install instructions (make sure you have development tools installed as well as PHP and its development components):
tar zxf php-jsmin-1.0.tgz
cd php-jsmin-1.0
phpize
sh ./configure
make
make install
(optional) in php.ini add the following line: extensions=jsmin.so
Sample code:
if (!extension_loaded('jsmin')) {
dl('jsmin.so');
}
header('Content-Type: text/javascript');
echo jsmin(file_get_contents('my.js'));
I hope you find it useful.
Thanks Eric and Igor, you guys are my hero! This is much better than jsmin-php. Your install instructions worked perfectly under Gentoo Linux without any tweaks.
You have inspired me too create a small PHP script to quickly minify javascript files on the commandline:
#!/usr/bin/php <?php /** * jsmin for the commandline * * Feel free to use and distribute as you wish. * Don't blame me for any damage this script might produce */ $instructions = "Usage: jsmin SOURCE [TARGET] Remove comments and unnecessary whitespace from JavaScript files. Example: jsmin test.js test.min.js"; try { if (empty($argv[1])) { throw new Exception('Missing SOURCE argument!'); } if (empty($argv[2])) { // no TARGET file specified, minify to STDOUT fwrite(STDOUT, trim(jsmin(file_get_contents($argv[1])))); } else if (!file_exists($argv[2])) { // TARGET file does not exist, minify to new file jsminPutContents(); } else { // TARGET file exists, ask to overwrite existing file fwrite(STDOUT, "Overwrite '{$argv[2]}'? [Y/N]: "); if (strtoupper(trim(fgets(STDIN))) === 'Y') { jsminPutContents(); } else { exit(fwrite(STDOUT, "user aborted!\n")); } } } catch (Exception $e) { fwrite(STDOUT, 'ERROR: ' . $e->getMessage() . "\n{$instructions}\n"); } function jsminPutContents() { global $argv; file_put_contents($argv[2], trim(jsmin(file_get_contents($argv[1])))); fwrite(STDOUT, "done!\n"); } // EOFThis code presumes that you are running PHP5, that PHP-CLI is located at /usr/bin/php, that the above script is named ‘jsmin’ and is executable and resides in your system PATH. The only thing I noticed is that jsmin outputs content with leading newlines, that is why I have wrapped the output with a trim(). Feel free to use this script at your own risk (of overwriting existing files) in any way you wish.
thanks for this module, Igor.
I’m wondering where I need to run make / make install from:
I’m on Ubuntu 9.04 and have got apache modules here:
/usr/lib/apache2/modules
and php modules here:
/usr/lib/php5/20060613/
From the directory that was created when you untared the file. You should be able to issue each one of those commands exactly as shown in that order.
thanks – I untarred the file in my home dir.
should i untar it from elsewhere?
(i am not seeing jsmin as a module in phpinfo after an apache restart, so I’m presuming untarring / make / make install from my home dir didn’t place the req’d files in the correct place[s])
update: i didn’t have php5-cli installed. I installed that, re-ran through Igor’s instructions above and ran a test. It’s working.
The output from make was less-than clear to me w/r/t where the libs we’re being placed. I had to run make install as su. (apologies if these are Duh!, but …)
there’s still no sign of jsmin in phpinfo, so I ran a test to confirm i can minify. Confirmed.
Very much looking forward to using this. Many thanks
I would recommend wrapping this in a function so you can include some caching. This will help you run minify only once an hour, max.
function minify($file)
{
$cache = ‘cache-’.$file;
if(!file_exists($cache) || filemtime($cache) > 3600)
{
$content = jsmin(file_get_contents($file));
file_put_contents($cache, $content);
}
return file_get_contents($cache);
}
Usage:
if (!extension_loaded(‘jsmin’))
{
dl(‘jsmin.so’);
}
header(‘Content-Type: text/javascript’);
echo minify(‘my.js’);
@smcnally
The extension gets installed to wherever your PHP extensions are kept. It varies for every installation. If you want to load jsmin in apache automatically, you need to edit your php.ini file and add the extension line.
JSMin by default strips conditional compilation. This can be avoided by a simple patch (but this modification isn’t spreaded through the web). Web Optimizer ( http://code.google.com/p/web-optimizator/ ) has JSMin included (among YUI Compressor and Packer) and can help in automation of minify and merging you client side logic.
Hi… I just installed this and it works great… does it work with CSS as well?
Hi there,
I’m trying to compile it on Win32 but I’m getting a lot of errors.
Do you or anyone has the DLL to win32?
Thanks,
Ricardo
@Ricardo
What’s a “Win32?” These are strange and weird words you’re using.
Eric, I’m tying to build the extension on Windows but it gives a lot of errors. There’s any mean to surpass this? Alternative to this?
Thanks,
Ricardo
I just realized this extension doesn’t seem to be multibyte safe
Can anyone else verify this?
@1001 Fonts
That may be the case. The extension is a straight port of jsmin.c with a few thread-safe changes. Do you have an example?
Try the folling PHP code. NOTE the code must be UTF8 encoded or at least some other multibyte encoding.
[code]
[/code]
outputs: var utf8Test=’ ‘;
expected: var utf8Test=’€’;
@igor
@igor
Try the folling PHP code. NOTE the code must be UTF8 encoded or at least some other multibyte encoding.
<?php echo (jsmin(“var utf8Test = ‘€’;”)); // EURO SIGN U+20AC, ?>
outputs: var utf8Test=’ ‘;
expected: var utf8Test=’€’;
Hi.
It seems that jsmin was made to work with older versions of PHP ( which needed old version of libtool ), because on my current (updated) distribution of Gentoo Linux (kernel 2.6.31, gcc 4.3.4, glibc 2.11.2, libtool 2.2.6b, php 5.2.13), it fails on compiling jsmin, after phpize and configure:
$ make
/bin/sh /usr/local/src/php-jsmin-1.0/libtool –mode=compile cc -I. -I/usr/local/src/php-jsmin-1.0 -DPHP_ATOM_INC -I/usr/local/src/php-jsmin-1.0/include -I/usr/local/src/php-jsmin-1.0/main -I/usr/local/src/php-jsmin-1.0 -I/usr/lib64/php5/include/php -I/usr/lib64/php5/include/php/main -I/usr/lib64/php5/include/php/TSRM -I/usr/lib64/php5/include/php/Zend -I/usr/lib64/php5/include/php/ext -I/usr/lib64/php5/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /usr/local/src/php-jsmin-1.0/jsmin.c -o jsmin.lo
/usr/local/src/php-jsmin-1.0/libtool: line 467: CDPATH: command not found
/usr/local/src/php-jsmin-1.0/libtool: line 1152: func_opt_split: command not found
libtool: Version mismatch error. This is libtool 2.2.6b, but the
libtool: definition of this LT_INIT comes from an older release.
libtool: You should recreate aclocal.m4 with macros from libtool 2.2.6b
libtool: and run autoconf again.
make: *** [jsmin.lo] Error 63
Do you have a newer version of jsmin which might work with this libtool 2.2.6b ?
great extension, @igor. as long as the php-cli package is installed, set up is an absolute breeze – took me less than 5 minutes to get everything running!
@igor, my previous comment was about installing this extension on a linux box. however, I’m trying to compile this on my local install of MAMP and it is compiling it as a 64-bit .so file, but my MAMP needs a ppc and/or i386 version in order for the extension to work successfully. any ideas on how to accomplish this?
Hi guys,
I patched the code for work with utf8:
—- utf8.patch —————————
— jsmin-old.c 2009-03-28 04:07:52.000000000 +0100
+++ jsmin.c 2010-09-01 10:12:34.355394829 +0200
@@ -101,7 +101,7 @@
int theB;
int theLookahead;
int error;
- char *data;
+ unsigned char *data;
smart_str *buf;
} jsmin_ctx;
@@ -366,7 +366,7 @@
Return a string to confirm that the module is compiled in */
PHP_FUNCTION(jsmin)
{
- char *arg = NULL;
+ unsigned char *arg = NULL;
int arg_len;
jsmin_ctx *ctx;
smart_str buf = {0};
———- end of file ———————–
——– PHP Test —————————-
——— end of file ————————
@Diego Campoy
——– PHP Test ———————————–
$utf8 = “résumé”;
echo ($utf8==jsmin($utf8))?”ok”:”fail”;
——– End of file ———————————–
@Phil, this is an issue with your php build.
@dale, I am not sure I follow. There is nothing in the package that forces the 64-bit build.
@Igor
I’m not sure that’s a problem with my php build, because the Gentoo Linux isn’t so new and unstable, and it’s used by a large linux comunity !
But to show you guys that I found a temporary solution for php-jsmin-1.0, that you can implement later in your configure/Makefile:
source=`dirname $0`
cc -I. -I$source -DPHP_ATOM_INC \
-I$source/include -I$source/main \
-I$source -I/usr/lib64/php5/include/php \
-I/usr/lib64/php5/include/php/main -I/usr/lib64/php5/include/php/TSRM \
-I/usr/lib64/php5/include/php/Zend -I/usr/lib64/php5/include/php/ext \
-I/usr/lib64/php5/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 \
-c $source/jsmin.c -o jsmin.o -fPIC -DPIC
cc -shared jsmin.o -Wl,-soname -Wl,jsmin.so -o jsmin.so
This worked very fine for me, compiled me the jsmin.so with no errors, and now I use it on 4 web servers that are in production !
Thanks for no help
I’ve installed jsmin.c and it’s a 1600x speedup (Yes, one six zero zero) over jsmin.php.
jsmin.php 25 secs to minify
jsmin.c 0.016 secs to minify
LIGHTNING, BABY BOY!
works great, many many thanks!
I was excited to try this out. However, after installing it correctly on my Mac and making the necessary change to my php.ini in MAMP, I get the following error:
PHP Warning: PHP Startup: Unable to load dynamic library ‘/Applications/MAMP/bin/php5.2/lib/php/extensions/no-debug-non-zts-20060613/jsmin.so’ – (null) in Unknown on line 0
Any idea how to get around this?
I don’t know anything about MAMP or Macs… but searching for that error shows that it’s a fairly common error on OSX with PHP. According to one person, it’s possible it didn’t compile properly, but I can’t make any guesses one way or the other. You may want to look for some help with compiling extensions on some Mac forums.
Thank you for this extension. I am using this for three months now and with pleasure
Diego, thanks for the quick fix, it works for me as well.
jsmin extension removes non-english characters that exists inside .js file
in my case , jsmin removes persian characters !
What is the reason !?
Hello Igor,
Could you host the project publicly?
@shiplu
You can download it here: http://www.ypass.net/downloads/php-jsmin/php-jsmin-1.0.tgz