JShrink is a php class that minifies javascript so that it can be delivered to the client quicker

Related tags

Frameworks JShrink
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-


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
An Hydrator class that can be used for filling object from array and extracting data from objects back to arrays.

Hydrator namespace: Meow\Hydrator Library that can hydrate (fill object with data from array) and extract data from object back to array. Installation

Meow 2 Feb 3, 2022
PHP Kafka client is used in PHP-FPM and Swoole. PHP Kafka client supports 50 APIs, which might be one that supports the most message types ever.

longlang/phpkafka Introduction English | 简体中文 PHP Kafka client is used in PHP-FPM and Swoole. The communication protocol is based on the JSON file in

Swoole Project 235 Dec 31, 2022
A magic PHP framework. Build reactive web apps without writing HTML, CSS, or JavaScript! Powered by Tailwind, Alpine, Laravel, & Livewire.

Malzahar A magic PHP framework. Build reactive web apps without writing HTML, CSS, or JavaScript! Powered by Tailwind, Alpine, Laravel, & Livewire. Re

null 26 Nov 17, 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
Hamtaro - the new web framework for front-end / back-end development using Php and Javascript.

Hamtaro framework About Technologies Controllers Components Commands Front-end development Getting Started About Hamtaro is the new web framework for

Phil'dy Jocelyn Belcou 3 May 14, 2022
PropertyInfo extracts information about PHP class' properties using metadata of popular sources.

PropertyInfo Component The PropertyInfo component extracts information about PHP class' properties using metadata of popular sources. Resources Docume

Symfony 1.9k Jan 5, 2023
A easy way to install your basic yii projetc, we have encrypt database password in phpfile, my class with alot funtions to help you encrypt and decrypt and our swoole server install just run ./yii swoole/start and be happy!

Yii 2 Basic Project Template with swoole and Modules Yii 2 Basic Project Template is a skeleton Yii 2 application best for rapidly creating small proj

null 3 Apr 11, 2022
A simple class that provides access to country & state list.

GeoData A simple class that provides access to country & state list. Installation composer require ahmard/geodata Usage Fetch country list <?php use

Ahmad Mustapha 4 Jun 20, 2022
TrailLamp is a lightweight, easy-to-use Php MVC framework that can be used to build web applications and REST APIs.

TrailLamp Introduction TrailLamp is a lightweight, easy-to-use Php MVC framework that can be used to build web applications and REST APIs. Installatio

Etorojah Okon 14 Jun 10, 2022
PHP Coroutine HTTP client - Swoole Humanization Library

PHP Coroutine HTTP client - Swoole Humanization Library

swlib 973 Dec 17, 2022
a framework for WebDevelop based on the mvc structure. The name of this project for Fun because everyone can use it. Completely simple and powerful structure for all your projects

A_A (-.-) ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ |-| █▄─▄▄─█▄─██─▄█─▄▄▄▄█─▄▄▄▄█▄─█─▄█─▄▄▄─██▀▄─██─▄

MasihGhaznavi 7 Jun 29, 2022
With this extension you can share data from your web pages to any social network!

Extension for sharing on social networks With this extension you can share data from your web pages to any social network! Features: SEO support, defa

Yii Maker 50 Oct 15, 2022
Silex Skeleton - a fully-functional Silex application that you can use as the skeleton for your new applications

Silex Skeleton - a fully-functional Silex application that you can use as the skeleton for your new applications

Silex 789 Dec 5, 2022
A set of shady Slim Framework middlewares that can solve some annoyances...

Shady A set of shady Slim Framework middlewares that can solve some annoyances... What does it contain? Available middlewares: ApacheVirtualHostFix Ur

Jan-Age Laroo 7 Jun 22, 2021
TCP Worker Client for RoadRunner 2.0 application server

RoadRunner TCP Plugin RoadRunner is an open-source (MIT licensed) high-performance PHP application server, load balancer, and process manager. It supp

Spiral Scout 8 Nov 26, 2022
Hprose asynchronous client & standalone server based on swoole

Hprose for Swoole Introduction Hprose is a High Performance Remote Object Service Engine. It is a modern, lightweight, cross-language, cross-platform,

Hprose 186 Sep 9, 2022
Yii2 console application used to write our processors of methods to responsible to client calling.

Microservice Application Skeleton Yii2 console application used to write our processors of methods to responsible to client calling. This application

Jafaripur 0 Mar 10, 2022
Simple, async SOAP webservice client, built on top of ReactPHP.

clue/reactphp-soap Simple, async SOAP web service client library, built on top of ReactPHP. Most notably, SOAP is often used for invoking Remote proce

Christian Lück 62 Jul 5, 2022
FuelPHP v1.x is a simple, flexible, community driven PHP 5.3+ framework, based on the best ideas of other frameworks, with a fresh start! FuelPHP is fully PHP 7 compatible.

FuelPHP Version: 1.8.2 Website Release Documentation Release API browser Development branch Documentation Development branch API browser Support Forum

Fuel 1.5k Dec 28, 2022