`
天梯梦
  • 浏览: 13747978 次
  • 性别: Icon_minigender_2
  • 来自: 洛杉矶
社区版块
存档分类
最新评论

php压缩多个CSS/JS文件

 
阅读更多

1. 压缩css

 

compress.php

 

<?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();
 

实例化:

 

test.php

 

<link href="compress.php" rel="stylesheet" type="text/css" />
<span id="tester">test</span>
 

 

2. 压缩js

 

利用jsmin类

 

来源:http://code.google.com/p/minify/

 

compress.php

 

header('Content-type: text/javascript');
require 'jsmin.php';
echo JSMin::minify(file_get_contents('common.js') . file_get_contents('common2.js'));
 

common.js

 

alert('first js');
 

common.js

 

alert('second js');
 

jsmin.php

 

<?php
/**
 * jsmin.php - extended PHP implementation of Douglas Crockford's JSMin.
 *
 * <code>
 * $minifiedJs = JSMin::minify($js);
 * </code>
 *
 * This is a direct port of jsmin.c to PHP with a few PHP performance tweaks and
 * modifications to preserve some comments (see below). Also, rather than using
 * stdin/stdout, JSMin::minify() accepts a string as input and returns another
 * string as output.
 * 
 * Comments containing IE conditional compilation are preserved, as are multi-line
 * comments that begin with "/*!" (for documentation purposes). In the latter case
 * newlines are inserted around the comment to enhance readability.
 *
 * 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> (PHP port)
 * @author Steve Clay <steve@mrclay.org> (modifications + cleanup)
 * @author Andrea Giammarchi <http://www.3site.eu> (spaceBeforeRegExp)
 * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
 * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
 * @license http://opensource.org/licenses/mit-license.php MIT License
 * @link http://code.google.com/p/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           = "\n";
    protected $b           = '';
    protected $input       = '';
    protected $inputIndex  = 0;
    protected $inputLength = 0;
    protected $lookAhead   = null;
    protected $output      = '';

    /**
     * Minify Javascript
     *
     * @param string $js Javascript to be minified
     * @return string
     */
    public static function minify($js)
    {
        // look out for syntax like "++ +" and "- ++"
        $p = '\\+';
        $m = '\\-';
        if (preg_match("/([$p$m])(?:\\1 [$p$m]| (?:$p$p|$m$m))/", $js)) {
            // likely pre-minified and would be broken by JSMin
            return $js;
        }
        $jsmin = new JSMin($js);
        return $jsmin->min();
    }

    /*
     * Don't create a JSMin instance, instead use the static function minify,
     * which checks for mb_string function overloading and avoids errors
     * trying to re-minify the output of Closure Compiler
     *
     * @private
     */
    public function __construct($input)
    {
        $this->input = $input;
    }
    
    /**
     * Perform minification, return result
     */
    public function min()
    {
        if ($this->output !== '') { // min already run
            return $this->output;
        }

        $mbIntEnc = null;
        if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
            $mbIntEnc = mb_internal_encoding();
            mb_internal_encoding('8bit');
        }
        $this->input = str_replace("\r\n", "\n", $this->input);
        $this->inputLength = strlen($this->input);

        $this->action(self::ACTION_DELETE_A_B);
        
        while ($this->a !== null) {
            // determine next command
            $command = self::ACTION_KEEP_A; // default
            if ($this->a === ' ') {
                if (! $this->isAlphaNum($this->b)) {
                    $command = self::ACTION_DELETE_A;
                }
            } elseif ($this->a === "\n") {
                if ($this->b === ' ') {
                    $command = self::ACTION_DELETE_A_B;
                // in case of mbstring.func_overload & 2, must check for null b,
                // otherwise mb_strpos will give WARNING
                } elseif ($this->b === null
                          || (false === strpos('{[(+-', $this->b)
                              && ! $this->isAlphaNum($this->b))) {
                    $command = self::ACTION_DELETE_A;
                }
            } elseif (! $this->isAlphaNum($this->a)) {
                if ($this->b === ' '
                    || ($this->b === "\n" 
                        && (false === strpos('}])+-"\'', $this->a)))) {
                    $command = self::ACTION_DELETE_A_B;
                }
            }
            $this->action($command);
        }
        $this->output = trim($this->output);

        if ($mbIntEnc !== null) {
            mb_internal_encoding($mbIntEnc);
        }
        return $this->output;
    }
    
    /**
     * ACTION_KEEP_A = Output A. Copy B to A. Get the next B.
     * ACTION_DELETE_A = Copy B to A. Get the next B.
     * ACTION_DELETE_A_B = Get the next B.
     */
    protected function action($command)
    {
        switch ($command) {
            case self::ACTION_KEEP_A:
                $this->output .= $this->a;
                // fallthrough
            case self::ACTION_DELETE_A:
                $this->a = $this->b;
                if ($this->a === "'" || $this->a === '"') { // string literal
                    $str = $this->a; // in case needed for exception
                    while (true) {
                        $this->output .= $this->a;
                        $this->a       = $this->get();
                        if ($this->a === $this->b) { // end quote
                            break;
                        }
                        if (ord($this->a) <= self::ORD_LF) {
                            throw new JSMin_UnterminatedStringException(
                                "JSMin: Unterminated String at byte "
                                . $this->inputIndex . ": {$str}");
                        }
                        $str .= $this->a;
                        if ($this->a === '\\') {
                            $this->output .= $this->a;
                            $this->a       = $this->get();
                            $str .= $this->a;
                        }
                    }
                }
                // fallthrough
            case self::ACTION_DELETE_A_B:
                $this->b = $this->next();
                if ($this->b === '/' && $this->isRegexpLiteral()) { // RegExp literal
                    $this->output .= $this->a . $this->b;
                    $pattern = '/'; // in case needed for exception
                    while (true) {
                        $this->a = $this->get();
                        $pattern .= $this->a;
                        if ($this->a === '/') { // end pattern
                            break; // while (true)
                        } elseif ($this->a === '\\') {
                            $this->output .= $this->a;
                            $this->a       = $this->get();
                            $pattern      .= $this->a;
                        } elseif (ord($this->a) <= self::ORD_LF) {
                            throw new JSMin_UnterminatedRegExpException(
                                "JSMin: Unterminated RegExp at byte "
                                . $this->inputIndex .": {$pattern}");
                        }
                        $this->output .= $this->a;
                    }
                    $this->b = $this->next();
                }
            // end case ACTION_DELETE_A_B
        }
    }
    
    protected function isRegexpLiteral()
    {
        if (false !== strpos("\n{;(,=:[!&|?", $this->a)) { // we aren't dividing
            return true;
        }
        if (' ' === $this->a) {
            $length = strlen($this->output);
            if ($length < 2) { // weird edge case
                return true;
            }
            // you can't divide a keyword
            if (preg_match('/(?:case|else|in|return|typeof)$/', $this->output, $m)) {
                if ($this->output === $m[0]) { // odd but could happen
                    return true;
                }
                // make sure it's a keyword, not end of an identifier
                $charBeforeKeyword = substr($this->output, $length - strlen($m[0]) - 1, 1);
                if (! $this->isAlphaNum($charBeforeKeyword)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    /**
     * Get next char. Convert ctrl char to space.
     */
    protected function get()
    {
        $c = $this->lookAhead;
        $this->lookAhead = null;
        if ($c === null) {
            if ($this->inputIndex < $this->inputLength) {
                $c = $this->input[$this->inputIndex];
                $this->inputIndex += 1;
            } else {
                return null;
            }
        }
        if ($c === "\r" || $c === "\n") {
            return "\n";
        }
        if (ord($c) < self::ORD_SPACE) { // control char
            return ' ';
        }
        return $c;
    }
    
    /**
     * Get next char. If is ctrl character, translate to a space or newline.
     */
    protected function peek()
    {
        $this->lookAhead = $this->get();
        return $this->lookAhead;
    }
    
    /**
     * Is $c a letter, digit, underscore, dollar sign, escape, or non-ASCII?
     */
    protected function isAlphaNum($c)
    {
        return (preg_match('/^[0-9a-zA-Z_\\$\\\\]$/', $c) || ord($c) > 126);
    }
    
    protected function singleLineComment()
    {
        $comment = '';
        while (true) {
            $get = $this->get();
            $comment .= $get;
            if (ord($get) <= self::ORD_LF) { // EOL reached
                // if IE conditional comment
                if (preg_match('/^\\/@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
                    return "/{$comment}";
                }
                return $get;
            }
        }
    }
    
    protected function multipleLineComment()
    {
        $this->get();
        $comment = '';
        while (true) {
            $get = $this->get();
            if ($get === '*') {
                if ($this->peek() === '/') { // end of comment reached
                    $this->get();
                    // if comment preserved by YUI Compressor
                    if (0 === strpos($comment, '!')) {
                        return "\n/*" . substr($comment, 1) . "*/\n";
                    }
                    // if IE conditional comment
                    if (preg_match('/^@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
                        return "/*{$comment}*/";
                    }
                    return ' ';
                }
            } elseif ($get === null) {
                throw new JSMin_UnterminatedCommentException(
                    "JSMin: Unterminated comment at byte "
                    . $this->inputIndex . ": /*{$comment}");
            }
            $comment .= $get;
        }
    }
    
    /**
     * Get the next character, skipping over comments.
     * Some comments may be preserved.
     */
    protected function next()
    {
        $get = $this->get();
        if ($get !== '/') {
            return $get;
        }
        switch ($this->peek()) {
            case '/': return $this->singleLineComment();
            case '*': return $this->multipleLineComment();
            default: return $get;
        }
    }
}

class JSMin_UnterminatedStringException extends Exception {}
class JSMin_UnterminatedCommentException extends Exception {}
class JSMin_UnterminatedRegExpException extends Exception {}
 

 

实例化:

 

test.php

 

<script type="text/javascript" src="fonts.php"></script>
 

 

 

分享到:
评论

相关推荐

    Javascript/CSS 多文件代码合并、安全压缩、优化(PHP版)

    压缩多个 js 方法: [removed] [removed] 压缩多个 CSS 方法: &lt;link rel="stylesheet" media="all" href="http://julying.com/lab/compress-js-css/file=/lab/coffee/layerImages/layer.css,/lab/coffee...

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

    通过PHP脚本引入jsmin.php,然后使用JSMin类的minify方法来合并并压缩多个JavaScript文件。如下所示: ```php &lt;?php header('Content-type:text/javascript'); require 'jsmin.php'; echo JSMin::minify(file_get_...

    多个css、js文件自动合并、压缩在线工具

    以下这篇文章给我们介绍的通过php javascript程序实现了对多个css、多个js文件进行自动合并、压缩是最好的解决方案。比如:你的网站引用了a.css和b.css两个css文件,php javascrip程序则将a.css和b.css自动合并、...

    Joomla CSS JS代码压缩插件

    Joomla CSS JS代码压缩插件通过删除这些冗余字符,并将多个文件合并成一个或少数几个文件,有效减少了网络传输的数据量。 插件的安装过程通常包括以下步骤: 1. 下载插件文件包,其中包括`jch_optimize.php`,这是...

    jscompress_js去空行压缩_php_

    "jscompress"即是指对JavaScript代码进行压缩的过程,它主要目的是去除不必要的空行、缩进和空白字符,同时可能还会合并多个脚本文件为一个,以进一步优化性能。 在"jscompress_js去空行压缩_php_"这个标题中,我们...

    PHP实现动态压缩js与css文件的方法

    总结起来,PHP实现动态压缩js与css文件的方法是通过自定义函数读取多个文件内容,进行合并和压缩,然后将压缩后的文件保存到服务器上,最后在HTML中引用这些新的压缩文件。这种方式可以显著提升网站性能,减少网络...

    2024 优化版 站长工具源码/网页工具箱/JS格式化/压缩网站源码自适应模板带管理后台

    2024.07月更新 请看演示 增加加了100多查询娱乐功能 这个是带手机版TOOL在线网页工具箱/站长工具源码/在线加密解密网站源码160个工具 带管理后台,是整站源码!!带安装教程!!! 演示站:...

    php压缩多个CSS为一个css的代码并缓存

    在PHP中,将多个CSS文件压缩成一个文件并进行缓存是一种常见的性能优化技术,它有助于减少HTTP请求的数量,加快页面加载速度,并节省带宽。下面我们将详细解释这个过程以及提供的代码片段。 首先,让我们看看这段...

    基于PHP的minify 自动压缩合并JS和CSS(减少请求数).zip

    "基于PHP的minify 自动压缩合并JS和CSS(减少请求数)"是一个解决这个问题的方案,它通过合并和压缩JavaScript (JS) 和 Cascading Style Sheets (CSS) 文件来减少网络请求的数量,从而加快页面的加载速度。 1. PHP ...

    php压缩HTML函数轻松实现压缩html/js/Css及注意事项

    压缩HTML的起因 如何提高网页加载速度 ,需要怎么对html页面优化相信是每个拟提高建站技术站长曾想到的问题,其实网页优化的方法还是很多。 有童鞋询问higrid如何 压缩HTML,也就是说能不能 把所有的html、js、Css在...

    基于PHP的minify自动压缩合并JS和CSS(减少请求数)源码.zip

    这个压缩包提供了一个PHP实现的解决方案,它可以帮助开发者整合多个JS和CSS文件为单个文件,并进行压缩,以降低网络请求的数量,提高网站的加载速度。 首先,我们需要理解为什么减少HTTP请求数量对网页性能至关重要...

    PHP生成压缩文,不带要压缩文件的根目录

    "PHP生成压缩文,不带要压缩文件的根目录"这个话题,主要涉及的是如何使用PHP的ZipArchive类来创建一个ZIP文件,但不包含源文件的根目录路径。下面将详细介绍这一知识点及其相关技术。 首先,我们需要了解PHP的Zip...

    传奇竞技游戏类网站模板,html+css+JavaScript+php

    综上所述,这个传奇竞技游戏类网站模板是一个完整的Web解决方案,结合了前端与后端技术,能够满足游戏社区的需求,包括用户互动、游戏资讯展示、用户登录注册以及后台数据管理等多个方面。开发者可以在此基础上进行...

    基于PHP的风吟PHP版JS在线压缩工具源码.zip

    【压缩包子文件的文件名称列表】中的 "132699490181644673" 可能代表的是压缩包内的一个或多个文件的ID或者哈希值,具体含义需要解压后查看。一般来说,这类源码包会包含HTML、PHP、CSS、JavaScript等文件,以及可能...

    html+css+js漂亮的个人主页

    4. **背景主题切换**:利用CSS预处理器(如Sass或Less)和JavaScript,可以创建多个背景主题,并提供一个切换按钮让用户选择。JavaScript会根据用户的选择更改body或特定元素的CSS类,从而改变背景样式。 5. **响应...

    js压缩工具.zip

    "js压缩工具.zip"这个压缩包很可能包含了若干个用于压缩和优化JavaScript文件的工具。 1. 压缩工具的作用: - 减小文件大小:通过删除空格、换行和不必要的字符,JS压缩工具能显著减小文件体积,加快网页加载速度...

    Yii安装EClientScript插件扩展实现css,js文件代码压缩合并加载功能

    2. 文件合并:合并是将多个CSS或JavaScript文件合并为一个文件,这样在页面加载时只需要一次网络请求。虽然合并可以减少HTTP请求的次数,但如果不注意,也可能导致加载不必要的文件,从而降低性能。因此,通常需要...

Global site tag (gtag.js) - Google Analytics