Javascript Minifier built in PHP

Overview

JShrink Build Status

License Latest Stable Version Coverage Status Total Downloads

JShrink is a php class that minifies javascript so that it can be delivered to the client quicker. This code can be used by any product looking to minify their javascript on the fly (although caching the results is suggested for performance reasons). Unlike many other products this is not a port into php but a native application, resulting in better performance.

Usage

Minifying your code is simple call to a static function-

<?php
include('vendor/autoload.php');

// Basic (default) usage.
$minifiedCode = \JShrink\Minifier::minify($js);

// Disable YUI style comment preservation.
$minifiedCode = \JShrink\Minifier::minify($js, array('flaggedComments' => false));

Results

  • Raw - 586,990
  • Gzip - 151,301
  • JShrink - 371,982
  • JShrink and Gzip - 93,507

Installing

Composer

Installing JShrink can be done through a variety of methods, although Composer is recommended.

"require": {
  "tedivm/jshrink": "~1.0"
}

Github

Releases of JShrink are available on Github.

License

JShrink is licensed under the BSD License. See the LICENSE file for details.

In the spirit of open source, use of this library for evil is discouraged but not prohibited.

Reporting Security and Vulnerability Issues

This project utilizes the Tidelift Security Reporting System for security and vulnerability reporting.

Support

Issues can be opened directly in Github for issues that aren't related to security.

Professionally supported JShrink is now available with Tidelift.

Comments
  • A different approach

    A different approach

    Hi,

    I found out about this package because Magento 2 is using it in its build process. The build process is very time consuming, and part this time is spent compressing Javascript files with JShrink. When I looked at the code it occurred to me that a different approach might make it much faster. This approach would be based on the pivotal use of the PHP function preg_replace_callback, which would process the entire Javascript file at once.

    Here's a bit of (very incomplete) code I used to test if this would work:

    $exp = "~(
                /\*!.*?\*/ |                                             # /* license */
                /\*.*?\*/ |                                             # /* comment */
                //[^\n]* |                                              # // comment
                /(?:\\\\/|[^/])+/[dgimsuy]*[ ]*[,;\n)] |                 # erg exp: /(ape|monkey)\/banana/mi;
                \"(?:\\\\\"|[^\"])*\" |                                 # double quoted string
                '(?:\\\\'|[^'])*' |                                     # single quoted string
                (?P<negatives1>--?)\s+(?P<negatives2>--?) |             # a - --b     a-- - b
                (?P<positives1>\+\+?)\s+(?P<positives2>\+\+?) |         # a + ++b     a++ + b
                (?:return|var) |                                        # operator keyword
                [ \t\n]+                                                # whitespace
            )~xs";
    
            $normalized = str_replace(["\r\n", "\r"], ["\n", "\n"], $js);
    
            $result = preg_replace_callback($exp, function($matches) {
    
                $match = $matches[1];
                $first = $match[0];
                switch ($first) {
                    case '"':
                        // remove line continuation
                        $string = str_replace("\\\n", "", $match);
                        return $string;
                    case ' ':
                        return '';
                    case "\n":
                        return '';
                    case "\t":
                        return '';
                }
                $firstTwo = substr($match, 0, 2);
                switch ($firstTwo) {
                    case '//':
                        return '';
                    case '/*':
                        return '';
                }
                switch ($match) {
                    case 'var':
                        return 'var ';
                    case 'return':
                        return 'return ';
                }
                if (isset($matches['negatives1']) && $matches['negatives1'] !== "") {
                    return $matches['negatives1'] . " " . $matches['negatives2'];
                }
                if (isset($matches['positives1']) && $matches['positives1'] !== "") {
                    return $matches['positives1'] . " " . $matches['positives2'];
                }
                return $match;
            }, $normalized);
    

    So, basically, the outermost loop is replaced by a single preg_replace_callback. It is much faster because it implements the inner loop with C code (the implementation of preg_replace_callback is written in C), rather than PHP code.

    Before I work this out in detail, I was wondering if you are open to this complete rewrite. I am willing to perform the complete rewrite myself, but there are also some points in which the new code will not be backwards compatible with the existing code, like checking if a regular expression is well formed and throwing a RuntimeException. This new code will not do that. Doubtlessly there will be some other minor points that are not completely backwards compatible. So the question is: are you willing to loose some of the compatibility for a signification increase in processing speed?

    If you are interested, I would like the help of some beta testers to debug my code. I just had this idea, it doesn't mean I make no mistakes working it out.

    Of course I can start a repository in my own domain, but then it would have to start its user base from the start. By rewriting JShrink it may benefit all of your users.

    What do you think?

    opened by garfix 17
  • performance tweaks

    performance tweaks

    The incentive was that with the xdebug profiler on I ran into timeout (30s) issues, tried to improve it a bit. You might be interested in this, i have tested a bit, all seems fine.

    • strict equality tests
    • regex /S optimize flag
    • omit cast to bool in while
    • empty instead of counting

    with xdebug on, this got me 50% faster generation (10 instead of 20s) without xdebug its barely noticible

    opened by birdspider 10
  • A few tests missing from test suite

    A few tests missing from test suite

    https://github.com/mrclay/minify/blob/master/min_unit_tests/_test_files/js/issue144.js https://github.com/mrclay/minify/blob/master/min_unit_tests/_test_files/js/condcomm.js https://github.com/mrclay/minify/blob/master/min_unit_tests/_test_files/js/issue132.js https://github.com/mrclay/minify/blob/master/min_unit_tests/_test_files/js/issue74.js

    Supporting things like a - ++b required quite a patch in JSMin.

    I'm still open to using this in Minify if it can handle all the same content and (ideall) faster.

    opened by mrclay 9
  • Regex Detection Failure

    Regex Detection Failure

    (rev:b3d0a82) Cannot detect this regex and fails with 'Stray Regex Pattern' error.

            return /\?/ .test( url ) ? "&" : "?";
    
    • This regex cannot get detected on line 233 because it doesn't have wrapping quotes.
    • And it gets detected on line 248, but it catches the ending of regex, because it has question mark before getting closed. saveRegex() gets called (after the end of regex)
    • So, saveRegex() function goes until the end of line and fails.
    opened by furkanmustafa 8
  • New release for PHP 8

    New release for PHP 8

    Since https://github.com/tedious/JShrink/pull/97 got merged, and https://github.com/tedious/JShrink/commit/ca8970bd84e78eabaf0daa30eb591161b4d71859 fix code wise incompatibility with PHP 8. Is there a new release coming soon?

    opened by WyriHaximus 7
  • Unclosed string at position on regEx

    Unclosed string at position on regEx

    It dies with: Uncaught exception 'RuntimeException' with message 'Unclosed string at position: 59'

    given this string: "var regEx = /[a-z0-9!#$%&'+/=?^{|}~-]+(?:.[a-z0-9!#$%&'_+/=?^_{|}~-]+)@(?:a-z0-9?.)+(?:[A-Z])\b/;"

    EDIT: The regEx is wrong, and shouldn't be like this. The start is /[a-z0-9!#$%&'+/ which normally completes a regex. The question is, I guess, whether JSShrink should still die or not.

    opened by OlofT 6
  • Add gitattributes w/ export-ignore

    Add gitattributes w/ export-ignore

    This will allow for a production ready version of JShink when archived/exported for release(s) and still allowing a development version within the repository.

    The export-ignore excludes un-needed files and directories when a branch is archived for release and these files are still included when the repo is cloned/forked.

    This would be very useful because releases are intended for production use and when users are using a package (via composer or zip), they most likely are not interested in downloading the source code as a whole into production, thus saving server disk space and meeting security protocol. Think of it as a .gitignore for releases.

    • e.g. /tests folder, or your .travis.yml file, etc. will not be included in the release zip(s)

    See: git-scm.com - Exporting-Your-Repository

    opened by CelticParser 4
  • Minifying a particular javascript script will corrupt it.

    Minifying a particular javascript script will corrupt it.

    I've realized that if I minify the jquery plugin qtip2 (nightly built) with JShrink by using $js = JShrink\Minifier::minify($js); this will corrupt the file and its execution.

    Here is the problematic part:

    Original:

    (i.innerHTML="<!--[if gt IE "+ ++t+"]><i></i><![endif]-->")&&
    i.getElementsByTagName("i")[0];
    

    will be:

    (i.innerHTML="<!--[if gt IE "+++t+"]><i></i><![endif]-->")&&
    i.getElementsByTagName("i")[0];
    

    (!) it is the missing space after the first plus.

    Any ideas how to solve this?

    opened by AntoniusGolly 4
  • tinyMCE problem

    tinyMCE problem

    Not sure if this is more of a tinyMCE thing or a JShrink thing. When loading up content that loads tinyMCE.init(), a couple requests are made to:

    www.(baseurl).com//langs/en.js

    When the proper URL is something like:

    www.(baseurl).com/en/asset/js/tinyMCE/langs/en.js

    I don't mind the fact that it's making a request, as much as it's making a request to the wrong place. There are a pair of slashes and the directory is off. Maybe I'll need to hack the tinyMCE code to fix this? I've read in other places that people have had issues minifying tinyMCE.

    Anyways, very good work. We're running a javascript-heavy site, and tinyMCE is the only thing that broke as a result of JShrink! ;)

    opened by joeperic 4
  • JShrink never finishes or is very slow when using PHP 8

    JShrink never finishes or is very slow when using PHP 8

    Originally reported in https://github.com/matomo-org/matomo/issues/16707

    Minimal testcase (using https://code.jquery.com/jquery-3.5.1.js):

    <?php
    ini_set('max_execution_time', 30);
    include('vendor/autoload.php');
    $js = file_get_contents("jquery-3.5.1.js");
    $minifiedCode = \JShrink\Minifier::minify($js);
    echo $minifiedCode;
    

    takes 30 seconds to run when calling with php8 script.php (but weirdly enough outputs a minified js which is only missing a ; at the end).

    using PHP 8.0.0RC2 (but the same issue also occurs in Matomo when using RC3)

    opened by Findus23 3
  • More performance tweaks

    More performance tweaks

    Hi,

    I've tried to go deeper into performance tweaks. Please review series of changes which I've prepared.

    I've bench-marked every improvement separately before deciding whether to add it.

    As a test I've run new and old version on JS library for 3D rendering (threejs-lib) which consists of 352 JavaScript files, 11MB. I compared MD5 of minified content for new and current-master versions of JShink - no changes found.

    Current master: real 0m10,164s user 0m10,118s sys 0m0,036s

    New version: real 0m9,469s user 0m9,454s sys 0m0,008s

    New version is 0.695 sec faster, 6.8% improvement (on this specific JS lib). IMO not bad :-)

    Andrey.

    opened by andrey-legayev 3
  • Spaces removed from nested template literals in some cases

    Spaces removed from nested template literals in some cases

    In certain cases nested template literals seem to cause some spaces being removed.

    These seem to work fine, and the minified output is the same:

    console.log(`aa ${`bb cc`}`);
    console.log(`aa ${true ? `bb cc` : `bb cc`}`);
    console.log(`aa ${`a bb cc`}`);
    

    In these cases some spaces get removed:

    console.log(`aa ${`, bb cc`}`);
    console.log(`aa ${`. bb cc`}`);
    

    When minified:

    console.log(`aa ${`,bb cc`}`);
    console.log(`aa ${`.bb cc`}`);
    
    opened by ilkkave 0
  • Some js not usable after JShrink minification (example: axios code)

    Some js not usable after JShrink minification (example: axios code)

    I tried to put into one .js file to minify count of file requests, first content of minified axios javascript, then some newline (comments etc) and then own code.

    Axios is sure a modern and popular thing which should be considered important, and if it minified is buggy, then possibly other llibraries using the same minification may cause the same issues (webpack based minification)

    Without shrinking it works fine, minified code from JSrink does not work anymore

    To repeat, just find axios cdn, try copypasting content to local js file, then add newline and some own simple command, like

    /* axios minified code first*/
    {put here contents from https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.min.js}
    
    /* own code */
    console.log(1234);
    document.body.innerHTML = 'WORKS!';
    
    

    then just use script tag in some html, and after loading check console

    opened by peminator 0
  • Fix regex, Update Minifier.php

    Fix regex, Update Minifier.php

    Fix regex line: example line - {"use strict";t.exports=function(t){return/^([a-z][a-z\d+-.]:)?///i.test(t)}} after processing, the code was not cut correctly {"use strict";t.exports=function(t){return/^([a-z][a-z\d+-.]:)?/\

    opened by dzandrey 0
  • Fix where

    Fix where "return/RegEX/" breaks minify

    tinymce.min.js contains the following Javascript:

    return/^[^:]+:\/\/\/?[^\/]+\//.test(t)
    

    JSShrink does not call the saveRegex method for this Javascript string as it is not a recognized RegEx starting point.

    By adding "n" to the strpos test before the saveRegex call, the return/RegEx/ situation is properly handled. In the above case.

    When it is not properly handled, the \//.test(t) part of the RegEx is treated as a comment and is improperly truncated for tineymce.min.js.

    opened by viable-hartman 0
  • code removed after url double slash  https://

    code removed after url double slash https://

    In code i returning a url "https://player.vimeo.com/api/player.js"

    getApiURL(){return "https://player.vimeo.com/api/player.js"}}

    but after minifying code is removed after "https:" because you code consider a url as comment after double slash. code after minified: getApiURL(){return "https:;

    opened by zanysoft 0
Releases(v1.4.0)
  • v1.3.3(Jun 28, 2019)

  • v1.3.2(Jun 19, 2019)

  • v1.3.0(Dec 8, 2017)

    • Support for Template Literals
    • Update dev dependencies to latest versions
    • Drop testing support for HHVM and PHP5.6
    • Add testing support to PHP7.2
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(May 30, 2017)

  • v1.1.0(Aug 2, 2015)

  • v1.0.1(Nov 11, 2014)

    This release fixes a bug where completely empty comments could be misinterpreted as just the opening or closing comment tag, rather than the whole thing, causing runtime errors or missing javascript code.

    Example comment:

    /**/
    
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(May 5, 2014)

    This release, besides being the first v1.0 release and thus having a stable API, includes:

    • Formatting updates for PSR-1 and PSR-2
    • Increased code coverage significantly.
    • Increased testing of Comments, Strings and Regex.
    • Added tests for error conditions to ensure proper exceptions are thrown.
    • Added additional test groups for feature requests and in development test cases.
    • Cleaned up stray lines that were being outputted around comments.
    • Reduced size of multiline strings even further!
    • Revamped "minify" static function to for efficiency.
    • Made code more portable by removing some old PHP 5.2 code.
    • Normalized Exception methods and made them more clear.
    • Added and updated a lot of the comments.
    • Removed a few bugs around edge cases in javascript (like "i + ++j").
    • Refactored code for improved clarity and development

    As always, thank you for the support! I hope JShrink makes all of your projects faster for all of your users.

    Source code(tar.gz)
    Source code(zip)
  • v0.5.2(Jan 14, 2014)

    This release is primarily a refactoring of the Test Suite (to make it actually functional) and a clean up of the secondary files themselves.

    The JShrink code itself is unchanged, and you should be able to update without issue.

    Source code(tar.gz)
    Source code(zip)
Owner
Tedious Developments
Libraries That Prevent Boredom
Tedious Developments
PHP class to generate bookmarklets from Javascript code

Bookmarklet Gen Convert readable Javascript code into bookmarklet links Features removes comments compresses code by removing extraneous spaces, but n

྅༻ Ǭɀħ ༄༆ཉ 13 Oct 5, 2022
Commenting program developed with Html & Css & Php JavaScript Languages ​​and MySql

CommentSystem [BETA] Commenting program developed with Html & Css & Php JavaScript Languages and MySql How does it work ? After you set up your Databa

Azad 0 May 19, 2022
The Asset component manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files.

Asset Component The Asset component manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files. Res

Symfony 2.9k Jan 5, 2023
Combines. minifies, and serves CSS or Javascript files

Welcome to Minify! Minify is an HTTP server for JS and CSS assets. It compresses and combines files and serves it with appropriate headers, allowing c

Steve Clay 3k Jan 7, 2023
Middleware to minify the Html, CSS and Javascript content using wyrihaximus/compress

middlewares/minifier Middleware to minify the Html, CSS and Javascript content using wyrihaximus/compress and the following compressors by default: wy

Middlewares 15 Oct 25, 2022
A simple but powerful API for processing & compiling assets built around Webpack

Webpack Encore: A Simple & Powerful Webpack API Webpack Encore is a simpler way to integrate Webpack into your application. It wraps Webpack, giving y

Symfony 2.1k Jan 5, 2023
Asset Management for PHP

Assetic Assetic is an asset management framework for PHP. Project status This project is not maintained anymore. Development has been taken over at ht

Kris Wallsmith 3.8k Jan 4, 2023
Munee: Standalone PHP 5.3 Asset Optimisation & Manipulation

Munee: Standalone PHP 5.3 Asset Optimisation & Manipulation #####On-The-Fly Image Resizing, On-the-fly LESS, SCSS, CoffeeScript Compiling, CSS & JavaS

Cody Lundquist 837 Dec 21, 2022
A PHP implementation of bower :bird:

Bowerphp An implementation of bower in PHP. https://bowerphp.github.io/ Installation $ composer require beelab/bowerphp Configuration Currently, you c

BeeLab 473 Dec 30, 2022
A Parser for CSS Files written in PHP. Allows extraction of CSS files into a data structure, manipulation of said structure and output as (optimized) CSS

PHP CSS Parser A Parser for CSS Files written in PHP. Allows extraction of CSS files into a data structure, manipulation of said structure and output

Raphael Schweikert 1.6k Jan 5, 2023
NotrinosERP is an open source, web-based enterprise management system that written in PHP and MySql.

NotrinosERP is an open source, web-based enterprise management system that written in PHP and MySql. NotrinosERP contains all the required modules for running any small to medium size businesses. It supports multi users, multi currencies, multi languages

Phương 56 Dec 20, 2022
Javascript Minifier built in PHP

JShrink JShrink is a php class that minifies javascript so that it can be delivered to the client quicker. This code can be used by any product lookin

Robert Hafner 25 Oct 8, 2022
YCOM Impersonate. Login as selected YCOM user 🧙‍♂️in frontend.

YCOM Impersonate Login as selected YCOM user in frontend. Features: Backend users with admin rights or YCOM[] rights, can be automatically logged in v

Friends Of REDAXO 17 Sep 12, 2022
Html Minifier adalah paket simpel untuk minify output Html, Css style, dan Javascript sebelum dirender ke browser untuk aplikasi Laravel anda.

Laravel Html Minifier Adalah Paket simpel untuk minify HTML, Css Style, dan Javascript sebelum dirender ke browser untuk aplikasi Laravel anda. Alat i

:D 16 Aug 17, 2022
A fast Javascript minifier that removes unnecessary whitespace and comments

js-minify A fast Javascript minifier that removes unnecessary whitespace and comments Installation If you are using Composer, use composer require gar

Patrick van Bergen 5 Aug 19, 2022
:clamp: HtmlMin: HTML Compressor and Minifier via PHP

??️ HtmlMin: HTML Compressor and Minifier for PHP Description HtmlMin is a fast and very easy to use PHP library that minifies given HTML5 source by r

Lars Moelleken 135 Dec 8, 2022
A simple HTML minifier for Laravel 5, 6 & 7.

Laravel HTMLMin Laravel HTMLMin is currently maintained by Raza Mehdi, and is a simple HTML minifier for Laravel. It utilises Mr Clay's Minify package

null 1k Jan 4, 2023
A simple HTML minifier for Laravel 5, 6 & 7.

Laravel HTMLMin Laravel HTMLMin is currently maintained by Raza Mehdi, and is a simple HTML minifier for Laravel. It utilises Mr Clay's Minify package

null 1k Jan 4, 2023
Laravel HTMLMin - a simple HTML minifier for Laravel

Laravel HTMLMin Laravel HTMLMin is currently maintained by Raza Mehdi, and is a simple HTML minifier for Laravel. It utilises Mr Clay's Minify package

null 948 Mar 15, 2022
Video Chat application built using Metered Video SDK, with PHP Laravel Backend and JavaScript Front-End

Group Video Chat App with PHP Laravel and JavaScript Powered by Metered Video SDK Overview This application is a highly scalable group video calling a

null 2 Aug 18, 2022