有没有好的Zend Framework + Minify实现?

8

有没有与Zend Framework集成Minify的好的实现?我正在寻找示例。

我希望有一个插件可以覆盖$this->headLink()并输出正确的压缩URL/内容。

编辑:

似乎我找到的大多数示例在某种形式上都没有完全优化。我正在寻找符合以下要求的解决方案:

将多个链接和脚本标签减少为一个请求(一个用于链接,一个用于脚本) 我看到的最接近的方法是将逗号分隔的字符串传递给/min/的请求路径,如下所示:

<script src="/min?f=file1.js,file2,js,file3.js" type="text/javascript"></script>

为什么不将所有脚本组合成一个文件,然后在磁盘上动态缓存它,这样你就不必在每个请求上都进行脚本的压缩了?
<script src="/js/app.js?someRandomStringHere" type="text/javascript"></script>

组合方面应该保持顺序(指prepend、append等)。
虽然我不太关心发送正确的过期标头,因为我在服务器端强制使用gzip、ETag和过期标头,但对其他用户来说,有这个选项会很有益。
最后,拥有一个生成压缩资产的构建脚本并不是坏事——只要它易于操作,并且不需要每次构建后进行代码更改。

我正在处理这个问题,已经收藏了并会随时通知您。 - Jake N
@jakenoble 这里有进展吗? - doremi
4个回答

3

这是我使用的代码,它展示了类以及使用案例。我已经快速地添加了注释,其中一些可能需要更改以匹配您的路径或者define() PUBLICPATH

class View_Helper_Minify extends Zend_View_Helper_Abstract
{
    public function minify($files, $ext, $folderName)
    {   
        // The folder of the files your about to minify
        // PUBLICPATH should be the path to your public ZF folder
        $folder = PUBLICPATH . $folderName . "/";

        // Set update needed flag to false
        $update_needed = false;

        // This is the file ext of the cached files
        $cacheFileExt = "." . $ext;

        // The list of files sent is exploded into an array
        $filesExploded = explode(',', $files);

        // The full cached file path is an md5 of the files string
        $cacheFilePath = $folder . md5($files) . $cacheFileExt;

        // The filename of the cached file 
        $cacheFileName = preg_replace("#[^a-zA-Z0-9\.]#", "", end(explode("/", $cacheFilePath)));

        // Obtains the modified time of the cache file
        $cacheFileDate = is_file($cacheFilePath) ? filemtime($cacheFilePath) : 0;

        // Create new array for storing the list of valid files
        $fileList = array();

        // For each file
        foreach($filesExploded as $f)
        {
            // determine full path of the full and append extension
            $f = $folder . $f . '.' . $ext;

            // If the determined path is a file
            if(is_file($f))
            {
                // If the file's modified time is after the cached file's modified time
                // Then an update of the cached file is needed
                if(filemtime($f) > $cacheFileDate)
                    $update_needed = true;

                // File is valid add to list 
                $fileList[] = $f;
            }
        }

        // If the cache folder's modified time is after the cached file's modified time
        // Then an update is needed
        if(filemtime($folder) > $cacheFileDate) 
            $update_needed = true;

        // If an update is needed then optmise the valid files
        if($update_needed)
            $this->optmiseFiles($fileList, $cacheFilePath, $ext);

        // Finally check if the cached file path is valid and return the absolute URL
        // for te cached file
        if(is_file($cacheFilePath))
            return "/" . $folderName . "/" . $cacheFileName;

        // Throw Exception
        throw new Exception("No minified file cached");             
    }

    private function optimise($code, $ext)
    {
        // Do not optmise JS files
        // I had problems getting JS files optmised and still function
        if($ext == "js")
            return $code;

        // Remove comments from CSS
        while(($i = strpos($code, '/*')) !== false)
        {
            $i2 = strpos($code, '*/',$i);

            if($i2 === false) 
                break;

            $code = substr($code, 0, $i).substr($code, $i2 + 2);
        }

        // Remove other elements from CSS
        $code = str_replace('/*','',$code);
        $code = str_replace("\n",' ',$code);
        $code = str_replace("\r",' ',$code);
        $code = str_replace("\t",' ',$code);
        $code = @ereg_replace('[ ]+',' ',$code);
        $code = str_replace(': ',':', $code);
        $code = str_replace('; ',';', $code);
        $code = str_replace(', ',',', $code);
        $code = str_replace(' :',':', $code);
        $code = str_replace(' ;',';', $code);
        $code = str_replace(' ,',',', $code);

        // Return optimised code
        return $code;
    }

    // Optmise the list of files
    private function optmiseFiles($fileList, $cacheFilePath, $ext)
    {
        // Empty String to start with
        $code = '';

        // Check files list in case just one file was passed
        if(is_array($fileList))
        {
            // Foreach of the valid files optmise the code if the file is valid
            foreach($fileList as $f)
                $code .= is_file($f) ? $this->optimise(implode('', file($f)), $ext) : '';
        }
        // Else if a valid file is passed optmise the code
        else
            $code = is_file($fileList) ? $this->optimise(implode('', file($fileList)), $ext) : '';

        // Open the cache file
        $f = @fopen($cacheFilePath, 'w');

        // If open successful
        if(is_resource($f))
        {
            // Write code to the cache file
            fwrite($f, $code);

            // close cache file
            fclose($f);
        }
    }   
}

在视图中,您可以像这样使用助手:
// Define an array of files, note you do not define the ext of those files
// The ext is defined as a param for the helper as this effects the optmisation  
$files = array("jquery-ui-1.8.7.custom",
            "jquery.pnotify.default",
            "jquery.pnotify.default.icons",
            "tipTip",
            "prettyPhoto",
            "custom");

// Get the absolute URL of the files which are imploded also pass the directory 'css' and ext 'css' 
$cssString = $this->minify(implode("," , $files), "css", "css");

// use baseURL() to output the full URL of the cached file and use it as normal with headLink()
echo $this->headLink()
->appendStylesheet($this->baseUrl($cssString));

以下是JavaScript版本的实现

$files = array("jquery-1.4.4.min",
            "jquery.pnotify.min",
            "jquery.tipTip.minified",
            "jquery.countdown.min",
            "jquery.prettyPhoto",
            "jquery.typewatch",
            "default.functions");

$jsString = $this->minify(implode("," , $files), "js", "scripts");

echo $this->headScript()->appendFile($this->baseUrl($jsString));

它能运行,但真的很混乱吗?我需要解释。 - Nandakumar
需要解释什么 - 都已经有注释了吗? - Jake N

2

我遇到了同样的问题,最终编写了两个插件来帮助我进行管理。您可以在http://blog.hines57.com/2011/03/13/zendframework-minify/上查看它们 - 再次感谢。其中一个的快速概述:

 * * ** PREREQUISITES **
 * This file expects that you have installed minify in ../ZendFramworkProject/Public/min 
 * and that it is working. If your location has changed, modify 
 * $this->$_minifyLocation to your current location.
 * 
 * ** INSTALLATION **
 * Simply drop this file into your ../ZendFramworkProject/application/views/helpers
 * directory.
 * 
 * ** USAGE **
 * In your Layout or View scripts, you can simply call minifyHeadLink
 * in the same way that you used to call headLink. Here is an example:
 * 
  echo $this->minifyHeadLink('/favicon.ico')             // Whatever was already loaded from Controller.
  ->prependStylesheet('http://example.com/js/sample.css')// 6th
  ->prependStylesheet('/js/jqModal.css')                 // 5th
  ->prependStylesheet('/js/jquery.alerts.css')           // 4th
  ->prependStylesheet('/templates/main.css')             // 3rd
  ->prependStylesheet('/css/project.css.php')            // 2nd
  ->prependStylesheet('/css/jquery.autocomplete.css')    // 1st
  ->appendStylesheet('/css/ie6.css','screen','lt IE 7'); // APPEND to make it Last
 *
 * 
 * This can be interesting because you will notice that 2nd is a php file, and we
 * have a reference to a favicon link in there as well as a reference to a css file on
 * another website. Because minify can't do anything with that php file (runtime configured 
 * css file) nor with CSS on other websites, and order is important,you would notice that 
 * the output in your browser will looks something like:
 * 
   <link href="/min/?f=/css/jquery.autocomplete.css" media="screen" rel="stylesheet" type="text/css" />
   <link href="/css/project.css.php" media="screen" rel="stylesheet" type="text/css" />
   <link href="/min/?f=/templates/main.css,/js/jquery.alerts.css,/js/jqModal.css" media="screen" 
               rel="stylesheet" type="text/css" />
   <link href="http://example.com/js/sample.css" media="screen" rel="stylesheet" type="text/css" />
   <link href="/favicon.ico" rel="shortcut icon" />
   <!--[if lt IE 7]> <link href="/css/ie6.css" media="screen" rel="stylesheet" type="text/css" /><![endif]-->

关于“将多个链接和脚本标签减少到一个请求(一个用于链接,一个用于脚本)”,我见过的最接近的方法是将逗号分隔的字符串传递给/min/。实际上,minify已经为您处理了这个问题。它会在第一次请求时创建并缓存文件,在所有后续请求中,对于该逗号分隔的字符串,只需提供缓存版本,而不是每次调用都要重新进行“重新”缩小。 - bubba

2
我现在正在尝试做同样的事情。我正在查看北卡罗来纳州立大学的OT框架,该框架基于Zend框架实现为视图助手。它有一个很好的类可以通过Google Code上的Minify来缩小所有headscripts和headlinks: http://ot.ncsu.edu/2010/03/03/getting-started-with-ot-framework/ Headscripts:
<?php

/**
 * Minifies the javascript files added via the minifyHeadScript helper using 
 * minify (http://code.google.com/p/minify/)
 *
 */
class Ot_View_Helper_MinifyHeadScript extends Zend_View_Helper_HeadScript
{

    protected $_regKey = 'Ot_View_Helper_MinifyHeadScript';

    public function minifyHeadScript($mode = Zend_View_Helper_HeadScript::FILE, $spec = null, $placement = 'APPEND', array $attrs = array(), $type = 'text/javascript')
    {
        return parent::headScript($mode, $spec, $placement, $attrs, $type);
    }

    public function toString()
    {
        $items = array();
        $scripts = array();
        $baseUrl = $this->getBaseUrl();

        // we can only support files
        foreach ($this as $item) {
            if (isset($item->attributes['src']) && !empty($item->attributes['src'])) {
                $scripts[] = str_replace($baseUrl, '', $item->attributes['src']);
            }
        }

        //remove the slash at the beginning if there is one
        if (substr($baseUrl, 0, 1) == '/') {
            $baseUrl = substr($baseUrl, 1);
        }

        $item = new stdClass();
        $item->type = 'text/javascript';
        $item->attributes['src'] = $this->getMinUrl() . '?b=' . $baseUrl . '&f=' . implode(',', $scripts);
        $scriptTag = $this->itemToString($item, '', '', '');

        return $scriptTag;
    }

    public function getMinUrl() {
        return $this->getBaseUrl() . '/min/';
    }

    public function getBaseUrl(){
        return Zend_Controller_Front::getInstance()->getBaseUrl();
    }
}

这里是headlinks的代码:

<?php

/**
 * Minifies the stylesheets added via the minifyHeadLink helper using 
 * minify (http://code.google.com/p/minify/)
 *
 */
class Ot_View_Helper_MinifyHeadLink extends Zend_View_Helper_HeadLink
{

    protected $_regKey = 'Ot_View_Helper_MinifyHeadLink';

    public function minifyHeadLink(array $attributes = null, $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND)
    {
        return parent::headlink($attributes, $placement);
    }

    public function toString()
        {
        $items = array();
        $stylesheets = array();
        $baseUrl = $this->getBaseUrl();

        foreach ($this as $item) {
            if ($item->type == 'text/css' && $item->conditionalStylesheet === false) {
                $stylesheets[$item->media][] = str_replace($baseUrl, '', $item->href);
            } else {
                $items[] = $this->itemToString($item);
            }
        }

        //remove the slash at the beginning if there is one
        if (substr($baseUrl, 0, 1) == '/') {
            $baseUrl = substr($baseUrl, 1);
        }

        foreach ($stylesheets as $media=>$styles) {
            $item = new stdClass();
            $item->rel = 'stylesheet';
            $item->type = 'text/css';
            $item->href = $this->getMinUrl() . '?b=' . $baseUrl . '&f=' . implode(',', $styles);
            $item->media = $media;
            $item->conditionalStylesheet = false;
            $items[] = $this->itemToString($item);
        }

        $link = implode($this->_escape($this->getSeparator()), $items);

        return $link;
    }

    public function getMinUrl() {
        return $this->getBaseUrl() . '/min/';
    }

    public function getBaseUrl(){
        return Zend_Controller_Front::getInstance()->getBaseUrl();
    }
}

0

嗯,抱歉我没有示例,但我可以帮助您解释如何操作。

我的简单工作流程如下:

1- 作为视图助手 在您的自定义库文件夹中,创建一个类,该类扩展了my_minify :: minify()的静态函数。 您可以创建一个视图助手,覆盖headLink()minfy类的功能。

2- 作为插件: 您可以创建一个插件,运行postdispatch来压缩整个结果视图,更多说明


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接