php实现压缩多个CSS与JS文件的方法


Posted in PHP onNovember 11, 2014

本文实例讲述了php实现压缩多个CSS与JS文件的方法。分享给大家供大家参考。具体实现方法如下:

1. 压缩css

<?php    

header('Content-type: text/css');    

ob_start("compress");    

function compress($buffer) {    

    /* remove comments */    

    $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);    

    /* remove tabs, spaces, newlines, etc. */    

    $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer);    

    return $buffer;    

}      

    

/* your css files */    

include('galleria.css');    

include('articles.css');    

    

ob_end_flush();

使用方法如下:
<link href="compress.php" rel="stylesheet" type="text/css" /><span id="tester">test</span>

2. 压缩js,利用jsmin类:

本实例源自:http://code.google.com/p/minify/

header('Content-type: text/javascript');    

require 'jsmin.php';    

echo JSMin::minify(file_get_contents('common.js') . file_get_contents('common2.js'));

其中jsmin.php文件如下:

<?php

/**

 * jsmin.php - PHP implementation of Douglas Crockford's JSMin.

 *

 * This is pretty much a direct port of jsmin.c to PHP with just a few

 * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and

 * outputs to stdout, this library accepts a string as input and returns another

 * string as output.

 *

 * PHP 5 or higher is required.

 *

 * Permission is hereby granted to use this version of the library under the

 * same terms as jsmin.c, which has the following license:

 *

 * --

 * Copyright (c) 2002 Douglas Crockford  (www.crockford.com)

 *

 * Permission is hereby granted, free of charge, to any person obtaining a copy of

 * this software and associated documentation files (the "Software"), to deal in

 * the Software without restriction, including without limitation the rights to

 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies

 * of the Software, and to permit persons to whom the Software is furnished to do

 * so, subject to the following conditions:

 *

 * The above copyright notice and this permission notice shall be included in all

 * copies or substantial portions of the Software.

 *

 * The Software shall be used for Good, not Evil.

 *

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

 * SOFTWARE.

 * --

 *

 * @package JSMin

 * @author Ryan Grove <ryan@wonko.com>

 * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)

 * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)

 * @copyright 2012 Adam Goforth <aag@adamgoforth.com> (Updates)

 * @license http://opensource.org/licenses/mit-license.php MIT License

 * @version 1.1.2 (2012-05-01)

 * @link https://github.com/rgrove/jsmin-php

 */

class JSMin {

  const ORD_LF            = 10;

  const ORD_SPACE         = 32;

  const ACTION_KEEP_A     = 1;

  const ACTION_DELETE_A   = 2;

  const ACTION_DELETE_A_B = 3;

  protected $a           = '';

  protected $b           = '';

  protected $input       = '';

  protected $inputIndex  = 0;

  protected $inputLength = 0;

  protected $lookAhead   = null;

  protected $output      = '';

  // -- Public Static Methods --------------------------------------------------

  /**

   * Minify Javascript

   *

   * @uses __construct()

   * @uses min()

   * @param string $js Javascript to be minified

   * @return string

   */

  public static function minify($js) {

    $jsmin = new JSMin($js);

    return $jsmin->min();

  }

  // -- Public Instance Methods ------------------------------------------------

  /**

   * Constructor

   *

   * @param string $input Javascript to be minified

   */

  public function __construct($input) {

    $this->input       = str_replace("\r\n", "\n", $input);

    $this->inputLength = strlen($this->input);

  }

  // -- Protected Instance Methods ---------------------------------------------

  /**

   * Action -- do something! What to do is determined by the $command argument.

   *

   * action treats a string as a single character. Wow!

   * action recognizes a regular expression if it is preceded by ( or , or =.

   *

   * @uses next()

   * @uses get()

   * @throws JSMinException If parser errors are found:

   *         - Unterminated string literal

   *         - Unterminated regular expression set in regex literal

   *         - Unterminated regular expression literal

   * @param int $command One of class constants:

   *      ACTION_KEEP_A      Output A. Copy B to A. Get the next B.

   *      ACTION_DELETE_A    Copy B to A. Get the next B. (Delete A).

   *      ACTION_DELETE_A_B  Get the next B. (Delete B).

  */

  protected function action($command) {

    switch($command) {

      case self::ACTION_KEEP_A:

        $this->output .= $this->a;

      case self::ACTION_DELETE_A:

        $this->a = $this->b;

        if ($this->a === "'" || $this->a === '"') {

          for (;;) {

            $this->output .= $this->a;

            $this->a       = $this->get();

            if ($this->a === $this->b) {

              break;

            }

            if (ord($this->a) <= self::ORD_LF) {

              throw new JSMinException('Unterminated string literal.');

            }

            if ($this->a === '\\') {

              $this->output .= $this->a;

              $this->a       = $this->get();

            }

          }

        }

      case self::ACTION_DELETE_A_B:

        $this->b = $this->next();

        if ($this->b === '/' && (

            $this->a === '(' || $this->a === ',' || $this->a === '=' ||

            $this->a === ':' || $this->a === '[' || $this->a === '!' ||

            $this->a === '&' || $this->a === '|' || $this->a === '?' ||

            $this->a === '{' || $this->a === '}' || $this->a === ';' ||

            $this->a === "\n" )) {

          $this->output .= $this->a . $this->b;

          for (;;) {

            $this->a = $this->get();

            if ($this->a === '[') {

              /*

                inside a regex [...] set, which MAY contain a '/' itself. Example: mootools Form.Validator near line 460:

                  return Form.Validator.getValidator('IsEmpty').test(element) || (/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(element.get('value'));

              */

              for (;;) {

                $this->output .= $this->a;

                $this->a = $this->get();

                if ($this->a === ']') {

                    break;

                } elseif ($this->a === '\\') {

                  $this->output .= $this->a;

                  $this->a       = $this->get();

                } elseif (ord($this->a) <= self::ORD_LF) {

                  throw new JSMinException('Unterminated regular expression set in regex literal.');

                }

              }

            } elseif ($this->a === '/') {

              break;

            } elseif ($this->a === '\\') {

              $this->output .= $this->a;

              $this->a       = $this->get();

            } elseif (ord($this->a) <= self::ORD_LF) {

              throw new JSMinException('Unterminated regular expression literal.');

            }

            $this->output .= $this->a;

          }

          $this->b = $this->next();

        }

    }

  }

  /**

   * Get next char. Convert ctrl char to space.

   *

   * @return string|null

   */

  protected function get() {

    $c = $this->lookAhead;

    $this->lookAhead = null;

    if ($c === null) {

      if ($this->inputIndex < $this->inputLength) {

        $c = substr($this->input, $this->inputIndex, 1);

        $this->inputIndex += 1;

      } else {

        $c = null;

      }

    }

    if ($c === "\r") {

      return "\n";

    }

    if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {

      return $c;

    }

    return ' ';

  }

  /**

   * Is $c a letter, digit, underscore, dollar sign, or non-ASCII character.

   *

   * @return bool

   */

  protected function isAlphaNum($c) {

    return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;

  }

  /**

   * Perform minification, return result

   *

   * @uses action()

   * @uses isAlphaNum()

   * @uses get()

   * @uses peek()

   * @return string

   */

  protected function min() {

    if (0 == strncmp($this->peek(), "\xef", 1)) {

        $this->get();

        $this->get();

        $this->get();

    } 

    $this->a = "\n";

    $this->action(self::ACTION_DELETE_A_B);

    while ($this->a !== null) {

      switch ($this->a) {

        case ' ':

          if ($this->isAlphaNum($this->b)) {

            $this->action(self::ACTION_KEEP_A);

          } else {

            $this->action(self::ACTION_DELETE_A);

          }

          break;

        case "\n":

          switch ($this->b) {

            case '{':

            case '[':

            case '(':

            case '+':

            case '-':

            case '!':

            case '~':

              $this->action(self::ACTION_KEEP_A);

              break;

            case ' ':

              $this->action(self::ACTION_DELETE_A_B);

              break;

            default:

              if ($this->isAlphaNum($this->b)) {

                $this->action(self::ACTION_KEEP_A);

              }

              else {

                $this->action(self::ACTION_DELETE_A);

              }

          }

          break;

        default:

          switch ($this->b) {

            case ' ':

              if ($this->isAlphaNum($this->a)) {

                $this->action(self::ACTION_KEEP_A);

                break;

              }

              $this->action(self::ACTION_DELETE_A_B);

              break;

            case "\n":

              switch ($this->a) {

                case '}':

                case ']':

                case ')':

                case '+':

                case '-':

                case '"':

                case "'":

                  $this->action(self::ACTION_KEEP_A);

                  break;

                default:

                  if ($this->isAlphaNum($this->a)) {

                    $this->action(self::ACTION_KEEP_A);

                  }

                  else {

                    $this->action(self::ACTION_DELETE_A_B);

                  }

              }

              break;

            default:

              $this->action(self::ACTION_KEEP_A);

              break;

          }

      }

    }

    return $this->output;

  }

  /**

   * Get the next character, skipping over comments. peek() is used to see

   *  if a '/' is followed by a '/' or '*'.

   *

   * @uses get()

   * @uses peek()

   * @throws JSMinException On unterminated comment.

   * @return string

   */

  protected function next() {

    $c = $this->get();

    if ($c === '/') {

      switch($this->peek()) {

        case '/':

          for (;;) {

            $c = $this->get();

            if (ord($c) <= self::ORD_LF) {

              return $c;

            }

          }

        case '*':

          $this->get();

          for (;;) {

            switch($this->get()) {

              case '*':

                if ($this->peek() === '/') {

                  $this->get();

                  return ' ';

                }

                break;

              case null:

                throw new JSMinException('Unterminated comment.');

            }

          }

        default:

          return $c;

      }

    }

    return $c;

  }

  /**

   * Get next char. If is ctrl character, translate to a space or newline.

   *

   * @uses get()

   * @return string|null

   */

  protected function peek() {

    $this->lookAhead = $this->get();

    return $this->lookAhead;

  }

}

// -- Exceptions ---------------------------------------------------------------

class JSMinException extends Exception {}

?>

希望本文所述对大家的php程序设计有所帮助。

PHP 相关文章推荐
PHP中file_exists与is_file,is_dir的区别介绍
Sep 12 PHP
Thinkphp使用mongodb数据库实现多条件查询方法
Jun 26 PHP
php中call_user_func函数使用注意事项
Nov 21 PHP
php实现可用于mysql,mssql,pg数据库操作类
Dec 13 PHP
Laravel 5框架学习之向视图传送数据
Apr 08 PHP
php实现多城市切换特效
Aug 09 PHP
解析WordPress中的post_class与get_post_class函数
Jan 04 PHP
php实现替换手机号中间数字为*号及隐藏IP最后几位的方法
Nov 16 PHP
php、mysql查询当天,查询本周,查询本月的数据实例(字段是时间戳)
Feb 04 PHP
thinkphp3.2实现跨控制器调用其他模块的方法
Mar 14 PHP
laravel 创建命令行命令的图文教程
Oct 23 PHP
Aliyun Linux 编译安装 php7.3 tengine2.3.2 mysql8.0 redis5的过程详解
Oct 20 PHP
详谈PHP文件目录基础操作
Nov 11 #PHP
浅谈PHP解析URL函数parse_url和parse_str
Nov 11 #PHP
php 魔术方法详解
Nov 11 #PHP
php多个文件及图片上传实例详解
Nov 10 #PHP
PHP文件上传判断file是否己选择上传文件的方法
Nov 10 #PHP
php数组操作之键名比较与差集、交集赋值的方法
Nov 10 #PHP
php json转换成数组形式代码分享
Nov 10 #PHP
You might like
详解WordPress中简码格式标签编写的基本方法
2015/12/22 PHP
JS性能优化笔记搜索整理
2013/08/21 Javascript
jQuery实现图片信息的浮动显示实例代码
2013/08/28 Javascript
windows8.1+iis8.5下安装node.js开发环境
2014/12/12 Javascript
jquery实现鼠标滑过显示二级下拉菜单效果
2015/08/24 Javascript
关于微信中a链接无法跳转问题
2016/08/02 Javascript
JS实现的模仿QQ头像资料卡显示与隐藏效果
2017/04/07 Javascript
nodejs入门教程三:调用内部和外部方法示例
2017/04/24 NodeJs
Express+Nodejs 下的登录拦截实现代码
2017/07/01 NodeJs
利用Javascript获取选择文本所在的句子详解
2017/12/03 Javascript
基于 Vue.js 2.0 酷炫自适应背景视频登录页面实现方式
2018/01/17 Javascript
Vue底层实现原理总结
2018/02/17 Javascript
微信小程序实现左右联动的实战记录
2018/07/05 Javascript
vue配置font-awesome5的方法步骤
2019/01/27 Javascript
JavaScript中Dom操作实例详解
2019/07/08 Javascript
JS实现动态星空背景效果
2019/11/01 Javascript
Vue 实现创建全局组件,并且使用Vue.use() 载入方式
2020/08/11 Javascript
Openlayers实现图形绘制
2020/09/28 Javascript
js实现星星海特效的示例
2020/09/28 Javascript
在 Python 应用中使用 MongoDB的方法
2017/01/05 Python
WINDOWS 同时安装 python2 python3 后 pip 错误的解决方法
2017/03/16 Python
Python实现的视频播放器功能完整示例
2018/02/01 Python
python使用turtle绘制分形树
2018/06/22 Python
移动端rem布局的两种实现方法
2018/01/03 HTML / CSS
使用html5+css3来实现slider切换效果告别javascript+css
2013/01/08 HTML / CSS
html5 figure和figcaption的使用方法
2018/09/10 HTML / CSS
如何利用cmp命令比较文件
2016/04/11 面试题
创建服务型党组织实施方案
2014/02/25 职场文书
《高尔基和他的儿子》教学反思
2014/04/09 职场文书
会计电算化专业求职信
2014/06/10 职场文书
2014年变电站工作总结
2014/12/19 职场文书
golang import自定义包方式
2021/04/29 Golang
Python中的 Set 与 dict
2022/03/13 Python
Python采集股票数据并制作可视化柱状图
2022/04/04 Python
vue封装数字翻牌器
2022/04/20 Vue.js
vue组件vue-esign实现电子签名
2022/04/21 Vue.js