We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 24812
    • 7 Posts
    I’ve created two plugins that minify CSS and JS (currently without compression) after the document has been rendered by ModX. No modifications to templates are needed, one have only to create plugin and directory in /assets/components/minify. Plugin output is stored in cache files, they get updated when ModX cache is updated or if you manually delete cache files or change script/css filename. Cache files are specific for script/css combinations within templates and contexts. There should be no issues for most of sites.

    Here are the scripts:

    MinifyCSS
    <?php
    $properties['css_path'] = $modx->getOption('css_path',$scriptProperties,MODX_ASSETS_PATH . 'components/minify/');
      $properties['css_url'] = $modx->getOption('css_url',$scriptProperties,MODX_ASSETS_URL . 'components/minify/');
    
    $properties[xPDO::OPT_CACHE_KEY] = $modx->getOption('cache_resource_key', $properties, 'default');
    $properties[xPDO::OPT_CACHE_HANDLER] = $modx->getOption('cache_resource_handler', $properties, 'xPDOFileCache');
    $properties[xPDO::OPT_CACHE_EXPIRES] = (integer) $modx->getOption(xPDO::OPT_CACHE_EXPIRES, $properties, 0);
    $properties['cacheOptions'] = array(
      xPDO::OPT_CACHE_KEY => $properties[xPDO::OPT_CACHE_KEY],
      xPDO::OPT_CACHE_HANDLER => $properties[xPDO::OPT_CACHE_HANDLER],
      xPDO::OPT_CACHE_EXPIRES => $properties[xPDO::OPT_CACHE_EXPIRES],
    );
    
    
    $scripts = preg_match_all('!<link(.*)href="(.*\.css)"(.*)>!i',$modx->documentOutput,$matches,PREG_OFFSET_CAPTURE);
    $k='';
    foreach($matches[2] as $k) {
      $key .= $k[0];
    }
    $properties['cachePageKey'] = $modx->context->get('key') . '/elements/minify/'. md5($key);
    $properties['cacheFileName'] = $modx->context->get('key'). '.' . md5($key) . '.css';
    $cached = false;
    
    if ($modx->getCacheManager()) {
      $cached = $modx->cacheManager->get($properties['cachePageKey'], $properties['cacheOptions']);
    } else
      return false;
    
    if (empty($cached) || !isset($cached['properties']) || !isset($cached['output'])) {
    
      $js = '';
      foreach($matches[2] as $script) {
        $fp = fopen($script[0],'r+');
        $jsTmp = fread($fp,filesize($script[0]));
        $js .= preg_replace('!url\((.*)\)!i','url('.MODX_BASE_URL.dirname($script[0]).'/\\1)',$jsTmp);
        fclose($fp);
      }
    
      if ($modx->getCacheManager()) {
        $cached = array('properties' => $properties, 'output' => $js);
        $modx->cacheManager->set($properties['cachePageKey'], $cached, $properties[xPDO::OPT_CACHE_EXPIRES], $properties['cacheOptions']);
        $fp = fopen($properties['css_path'].$properties['cacheFileName'],'w');
        fwrite($fp,$js);
        fclose($fp);
      }
    
    }
    
    
      $modx->documentOutput = preg_replace('!<link(.*)href="(.*\.css)"(.*)>!i','',$modx->documentOutput);
    
      $modx->documentOutput = substr($modx->documentOutput,0,$matches[0][0][1]) . '<link rel="stylesheet" type="text/css" href="'.$properties['css_url'].$properties['cacheFileName'].'" />' . substr($modx->documentOutput,$matches[0][0][1]);


    MinifyJS
    <?php
    $properties['js_path'] = $modx->getOption('js_path',$scriptProperties,MODX_ASSETS_PATH . 'components/minify/');
      $properties['js_url'] = $modx->getOption('js_url',$scriptProperties,MODX_ASSETS_URL . 'components/minify/');
    
    $properties[xPDO::OPT_CACHE_KEY] = $modx->getOption('cache_resource_key', $properties, 'default');
    $properties[xPDO::OPT_CACHE_HANDLER] = $modx->getOption('cache_resource_handler', $properties, 'xPDOFileCache');
    $properties[xPDO::OPT_CACHE_EXPIRES] = (integer) $modx->getOption(xPDO::OPT_CACHE_EXPIRES, $properties, 0);
    $properties['cacheOptions'] = array(
      xPDO::OPT_CACHE_KEY => $properties[xPDO::OPT_CACHE_KEY],
      xPDO::OPT_CACHE_HANDLER => $properties[xPDO::OPT_CACHE_HANDLER],
      xPDO::OPT_CACHE_EXPIRES => $properties[xPDO::OPT_CACHE_EXPIRES],
    );
    
    
    $scripts = preg_match_all('!<script(.*)src="(.*)"(.*)></script>!i',$modx->documentOutput,$matches,PREG_OFFSET_CAPTURE);
    $k='';
    foreach($matches[2] as $k) {
      $key .= $k[0];
    }
    $properties['cachePageKey'] = $modx->context->get('key') . '/elements/minify/'. md5($key);
    $properties['cacheFileName'] = $modx->context->get('key'). '.' . md5($key) . '.js';
    $cached = false;
    
    if ($modx->getCacheManager()) {
      $cached = $modx->cacheManager->get($properties['cachePageKey'], $properties['cacheOptions']);
    } else
      return false;
    
    if (empty($cached) || !isset($cached['properties']) || !isset($cached['output'])) {
    
      $js = '';
      foreach($matches[2] as $script) {
        $fp = fopen($script[0],'r+');
        $js .= fread($fp,filesize($script[0]));
        fclose($fp);
      }
    
      if ($modx->getCacheManager()) {
        $cached = array('properties' => $properties, 'output' => $js);
        $modx->cacheManager->set($properties['cachePageKey'], $cached, $properties[xPDO::OPT_CACHE_EXPIRES], $properties['cacheOptions']);
        $fp = fopen($properties['js_path'].$properties['cacheFileName'],'w');
        fwrite($fp,$js);
        fclose($fp);
      }
    
    }
    
    
      $modx->documentOutput = preg_replace('!<script(.*)src="(.*)"(.*)></script>!i','',$modx->documentOutput);
    
      $modx->documentOutput = substr($modx->documentOutput,0,$matches[0][0][1]) . '<script type="text/javascript" src="'.$properties['js_url'].$properties['cacheFileName'].'"></script>' . substr($modx->documentOutput,$matches[0][0][1]);


    For both check OnWebPagePrerender event.

    hope those will help you earning some YSlow points ;-)

    The scripts are not optimized in any way, and currently I do not plan to convert them to packages - lacking of time ;-) As of my observations page rendering time is not affected significantly.

    MinifyCSS works only for relative paths - it is ok for all my works.

    You can see them work here http://www.iqfm.eu (have a look at source)

    If you need to work on css or javascript just disable plugins and everything will be untouched ;-)

    ps sorry for my eng, 15 years after I learned and not using too often now.
      • 20413
      • 2,877 Posts
      COool! cool
        @hawproductions | http://mrhaw.com/

        Infograph: MODX Advanced Install in 7 steps:
        http://forums.modx.com/thread/96954/infograph-modx-advanced-install-in-7-steps

        Recap: Portland, OR (PDX) MODX CMS Meetup, Oct 6, 2015. US Bancorp Tower
        http://mrhaw.com/modx_portland_oregon_pdx_modx_cms_meetup_oct_2015_us_bancorp_tower
        • 1331
        • 129 Posts
        This is very cool. However, I just tried to use it and the JS minifier didn’t output any data to the file it created. Any ideas?
          • 13622
          • 74 Posts
          Thanks! I’m going to give it a try on my test site...very cool.
            • 24812
            • 7 Posts
            Quote from: abelafonte at Oct 19, 2010, 08:46 PM

            This is very cool. However, I just tried to use it and the JS minifier didn’t output any data to the file it created. Any ideas?
            nope. Maybe you could PM me the url of your site.

            [edit] Maybe it is &#8203; which was appended in the last lines of both scripts. Just remove it.
              • 5160
              • 118 Posts
              Quote from: abelafonte at Oct 19, 2010, 08:46 PM

              This is very cool. However, I just tried to use it and the JS minifier didn’t output any data to the file it created. Any ideas?

              I have the same issue on Revolution 2.0.4-pl2. Can’t see any reference to the &#8203; zero width space character remek mentioned. Was it in the original code block above then removed with an edit?

              Anyone got the plugin running successfully?

              I was looking into CSS/JS Minification/Concatenation options and was about to settle on spending some time on http://code.google.com/p/minify/ then I found this thread which provides some interesting options.
                • 34022 ☆ A M B ☆
                • 91 Posts
                Cleaned it, expanded it, and submitted it as a package (waiting for approval now). Included a simple asynchronous JavaScript example and a filter using the "min" keyword. Didn’t spend too much time optimizing the classes/ settings, but it really cuts down the load time of one of my FoxyCart sites.

                Package Details:
                ID: 1604
                Name: Minify 0.1.0-beta

                Note: Needs a minor fix to enable the minify function (right now it’s only concatenation). Will re-upload once it’s up.
                  WebsiteZen.com - MODX and E-Commerce web development in the San Francisco Bay Area
                  • 1331
                  • 129 Posts
                  flippin sweet! can’t wait to grab this one.
                    • 5160
                    • 118 Posts
                    Looking forward to trying this out. I spent some time hooking up http://code.google.com/p/minify/ to one of my sites with a snippet and couple of TVs but am not entirely happy using it as it’s a fairly hefty package which I would struggle to debug if anything went wrong. It also uses it’s own caching system where I’d prefer to use the one built into MODx. I do like the ability to define ’groups’ of scripts eg. a core set that are required in the document <head> for each page like jquery and a set that can be loaded late on at the closing </body> tag for a few extra YSlow points.

                    This sounds good though - hopefully it can be one of the first packages I install on each new site.
                      • 14822
                      • 61 Posts
                      This plugin work? because I put in my website and not work appropriately, the script generated a empty file in assets/components/minify. I used modx 2.0.8 any can help me or say a alternative?

                      tnx