如何轻松地在 PHP 中缩小 JS ......或其他
Posted
技术标签:
【中文标题】如何轻松地在 PHP 中缩小 JS ......或其他【英文标题】:How to minify JS in PHP easily...Or something else 【发布时间】:2012-06-15 13:08:59 【问题描述】:我已经环顾四周了,但我还是有点困惑。
我尝试了 Crockford 的 JSMin,但是 Win XP 出于某种原因无法解压缩可执行文件。
我真正想要的是一个简单易用的 JS 缩小器,它使用 php 来缩小 JS 代码并返回结果。
之所以会这样,是因为: 我有 2 个文件(例如)正在处理:scripts.js 和 scripts_template.js
scripts_template 是我写出的普通代码——然后我必须将其缩小并将缩小后的脚本粘贴到 scripts.js——我在我的网站上实际使用的那个。
我想通过在我的页面上简单地做这样的事情来消除中间人:
<script type="text/javascript" src="scripts.php"></script>
然后是scripts.php的内容:
<?php include("include.inc"); header("Content-type:text/javascript"); echo(minify_js(file_get_contents("scripts_template.js")));
这样,每当我更新我的 JS 时,我就不必经常去网站缩小它并将其重新粘贴到 scripts.js 中——一切都会自动更新。
是的,我也尝试过 Crockford 的 PHP Minifier 并且我已经查看了 PHP Speedy,但我还不了解 PHP 类...有没有猴子可以理解的东西,也许是正则表达式?
我们如何让这更简单?
我只想删除制表符空格——我仍然希望我的代码可读。
脚本并不是让我的网站严重滞后,只是有总比没有好。
标签删除,有人吗?如果可能的话,如何完全删除空白行?
【问题讨论】:
正则表达式不会很快缩小 JS 代码。 相关: ***.com/a/33844247/1163000 如果你的代码足够短,你可以试试UglifyJS.php,但是长代码会很慢。 【参考方案1】:JavaScriptPacker 从 2008 年开始工作,非常简单
【讨论】:
【参考方案2】:使用“PHPWee”:https://github.com/searchturbine/phpwee-php-minifier
(也使用JSmin
),我将@Robert K 解决方案推得更远一点。
此解决方案允许缩小 CSS 和 JS 文件。如果找不到非缩小文件,它将返回一个空字符串。如果缩小文件比非缩小文件旧,它将尝试创建它。如果压缩文件不存在,它将为压缩文件创建一个子文件夹。如果该方法可以成功地缩小文件,它会在 <script>
(javascript) 或 <link>
(CSS) 标记中返回它。否则,该方法将在正确的标记中返回非缩小版本。
注意:使用 PHP 7.0.13 测试
/**
* Try to minify the JS/CSS file. If we are not able to minify,
* returns the path of the full file (if it exists).
*
* @param $matches Array
* 0 = Full partial path
* 1 = Path without the file
* 2 = File name and extension
*
* @param $fileType Boolean
* FALSE: css file.
* TRUE: js file
*
* @return String
*/
private static function createMinifiedFile(array $matches, bool $fileType)
if (strpos($matches[1], 'shared_code') !== false)
$path = realpath(dirname(__FILE__)) . str_replace(
'shared_code',
'..',
$matches[1]
);
else
$path = realpath(dirname(__FILE__)) .
"/../../" . $matches[1];
if (is_file($path . $matches[2]))
$filePath = $link = $matches[0];
$min = 'min/' . str_replace(
'.',
'.min.',
$matches[2]
);
if (!is_file($path . $min) or
filemtime($path . $matches[2]) >
filemtime($path . $min)
)
if (!is_dir($path . 'min'))
mkdir($path . 'min');
if ($fileType) // JS
$minified = preg_replace(
array(
'/(\))\R()/',
'/()\R/'
),
array(
'$1$2',
'$1'
),
Minify::js(
(string) file_get_contents(
$path . $matches[2]
)
)
);
else // CSS
$minified = preg_replace(
'@/\*(?:[\r\s\S](?!\*/))+\R?\*/@', //deal with multiline comments
'',
Minify::css(
(string) file_get_contents(
$path . $matches[2]
)
)
);
if (!empty($minified) and file_put_contents(
$path . $min,
$minified
)
)
$filePath = $matches[1] . $min;
else // up-to-date
$filePath = $matches[1] . $min;
else // full file doesn't exists
$filePath = "";
return $filePath;
/**
* Return the minified version of a CSS file (must end with the .css extension).
* If the minified version of the file is older than the full CSS file,
* the CSS file will be shrunk.
*
* Note: An empty string will be return if the CSS file doesn't exist.
*
* Note 2: If the file exists, but the minified file cannot be created,
* we will return the path of the full file.
*
* @link https://github.com/searchturbine/phpwee-php-minifier Source
*
* @param $path String name or full path to reach the CSS file.
* If only the file name is specified, we assume that you refer to the shared path.
*
* @return String
*/
public static function getCSSMin(String $path)
$link = "";
$matches = array();
if (preg_match(
'@^(/[\w-]+/view/css/)?([\w-]+\.css)$@',
$path,
$matches
)
)
if (empty($matches[1])) // use the default path
$matches[1] = self::getCssPath();
$matches[0] = $matches[1] . $matches[2];
$link = self::createMinifiedFile($matches, false);
else
$link = "";
return (empty($link) ?
'' :
'<link rel="stylesheet" href="' . $link . '">'
);
/**
* Return the path to fetch CSS sheets.
*
* @return String
*/
public static function getCssPath()
return '/shared_code/css/' . self::getCurrentCSS() . "/";
/**
* Return the minified version of a JS file (must end with the .css extension).
* If the minified version of the file is older than the full JS file,
* the JS file will be shrunk.
*
* Note: An empty string will be return if the JS file doesn't exist.
*
* Note 2: If the file exists, but the minified file cannot be created,
* we will return the path of the full file.
*
* @link https://github.com/searchturbine/phpwee-php-minifier Source
*
* @param $path String name or full path to reach the js file.
*
* @return String
*/
public static function getJSMin(String $path)
$matches = array();
if (preg_match(
'@^(/[\w-]+(?:/view)?/js/)([\w-]+\.js)$@',
$path,
$matches
)
)
$script = self::createMinifiedFile($matches, true);
else
$script = "";
return (empty($script) ?
'' :
'<script src="' . $script . '"></script>'
);
在 (Smarty) 模板中,您可以像这样使用这些方法:
$PageController->getCSSMin("main_frame.css")
//Output: <link rel="stylesheet" href="/shared_code/css/default/min/main_frame.min.css">
$PageController->getCSSMin("/gem-mechanic/view/css/gem_mechanic.css")
//Output: <link rel="stylesheet" href="/gem-mechanic/view/css/min/gem_mechanic.min.css">
$PageController->getJSMin("/shared_code/js/control_utilities.js")
//Output: <script src="/shared_code/js/min/control_utilities.min.js"></script>
$PageController->getJSMin("/PC_administration_interface/view/js/error_log.js")
//Output: <script src="/PC_administration_interface/view/js/min/error_log.min.js"></script>
单元测试:
/**
* Test that we can minify CSS files successfully.
*/
public function testGetCSSMin()
//invalid style
$this->assertEmpty(
PageController::getCSSMin('doh!!!')
);
//shared style
$path = realpath(dirname(__FILE__)) . '/../css/default/min/main_frame.min.css';
if (is_file($path))
unlink ($path);
$link = PageController::getCSSMin("main_frame.css");
$this->assertNotEmpty($link);
$this->assertEquals(
'<link rel="stylesheet" href="/shared_code/css/default/min/main_frame.min.css">',
$link
);
$this->validateMinifiedFile($path);
//project style
$path = realpath(dirname(__FILE__)) . '/../../gem-mechanic/view/css/min/gem_mechanic.min.css';
if (is_file($path))
unlink ($path);
$link = PageController::getCSSMin("/gem-mechanic/view/css/gem_mechanic.css");
$this->assertNotEmpty($link);
$this->assertEquals(
'<link rel="stylesheet" href="/gem-mechanic/view/css/min/gem_mechanic.min.css">',
$link
);
$this->validateMinifiedFile($path);
/**
* Test that we can minify JS files successfully.
*/
public function testGetJSMin()
//invalid script
$this->assertEmpty(
PageController::getJSMin('doh!!!')
);
//shared script
$path = realpath(dirname(__FILE__)) . '/../js/min/control_utilities.min.js';
if (is_file($path))
unlink ($path);
$script = PageController::getJSMin("/shared_code/js/control_utilities.js");
$this->assertNotEmpty($script);
$this->assertEquals(
'<script src="/shared_code/js/min/control_utilities.min.js"></script>',
$script
);
$this->validateMinifiedFile($path);
//project script
$path = realpath(dirname(__FILE__)) . '/../../PC_administration_interface/view/js/min/error_log.min.js';
if (is_file($path))
unlink ($path);
$script = PageController::getJSMin("/PC_administration_interface/view/js/error_log.js");
$this->assertNotEmpty($script);
$this->assertEquals(
'<script src="/PC_administration_interface/view/js/min/error_log.min.js"></script>',
$script
);
$this->validateMinifiedFile($path);
/**
* Make sure that the minified file exists and that its content is valid.
*
* @param $path String the path to reach the file
*/
private function validateMinifiedFile(string $path)
$this->assertFileExists($path);
$content = (string) file_get_contents($path);
$this->assertNotEmpty($content);
$this->assertNotContains('/*', $content);
$this->assertEquals(
0,
preg_match(
'/\R/',
$content
)
);
补充说明:
-
在
phpwee.php
中,我必须将<?
替换为<?php
。
我的命名空间有问题(函数class_exists()
无法找到这些类,即使它们在同一个文件中)。我通过删除每个文件中的命名空间解决了这个问题。
【讨论】:
【参考方案3】:我已经使用Douglas Crockford 的PHP implementation JSMin 已经有一段时间了。连接文件时可能会有一点风险,因为闭包末尾可能缺少分号。
缓存缩小的输出并回显缓存的内容是一个明智的想法,只要它比源文件更新即可。
require 'jsmin.php';
if(filemtime('scripts_template.js') < filemtime('scripts_template.min.js'))
read_file('scripts_template.min.js');
else
$output = JSMin::minify(file_get_contents('scripts_template.js'));
file_put_contents('scripts_template.min.js', $output);
echo $output;
你也可以试试JShrink。我以前从未使用过它,因为我以前没有遇到过 JSMin 的困难,但是下面的这段代码应该可以解决问题。我没有意识到这一点,但是 JShrink 需要 PHP 5.3 和命名空间。
require 'JShrink/Minifier.php';
if(filemtime('scripts_template.js') < filemtime('scripts_template.min.js'))
read_file('scripts_template.min.js');
else
$output = \JShrink\Minifier::minify(file_get_contents('scripts_template.js'));
file_put_contents('scripts_template.min.js', $output);
echo $output;
【讨论】:
我尝试使用它,但它并没有缩小整个代码。事实上,它在脚本中途削减了代码,所以我正处于 for() 循环的中间,这无论如何都会导致脚本损坏。 @RickyAYoder 是否有任何通知或错误输出?这可能是您的 Javascript 中的语法错误。 不。当我运行手工制作且未缩小的脚本时,不会报告任何错误。 另外请注意,除非他们这样说,否则这些包通常不支持 getter/setter。如果你的环境中确实有 Node.js,我建议改用 UglifyJS。 我对我的一个源文件进行了测试。 jsmin:(46,385 => 26,031 字节)。 JShrink:(463,85->26,027 字节)。非常相似的表现。但是,javascript-minifier.com 将其缩小到 19,526 字节,因为它用较短的版本替换了长变量名。【参考方案4】:根据您的服务器的限制(例如,不在safe mode 中运行),也许您还可以在PHP 之外寻找一个缩小器并使用shell_exec()
运行它。例如,如果您可以在服务器上运行 Java,请将 YUI Compressor 的副本放在服务器上并直接使用。
那么 scripts.php 会是这样的:
<?php
$cmd = "java -cp [path-to-yui-dir] -jar [path-to-yuicompressor.jar] [path-to-scripts_template.js]";
echo(shell_exec($cmd));
?>
其他建议:在部署到服务器之前,将缩小步骤构建到您的开发工作流程中。例如,我将 Eclipse PHP 项目设置为将 JS 和 CSS 文件压缩到“build”文件夹中。像魅力一样工作。
【讨论】:
为一个小型实用程序启动一个 JAVA 应用程序对我来说似乎是一个巨大的膨胀。不可能按照 OP 的要求将此解决方案放入请求-响应流中。 您所说的并不完全适用于 Java 应用程序。对于任何实用程序,重新缩小每个请求都是不必要的费用。注意Robert-K's earlier advice 缓存结果或我的“其他建议”,将其移动到自动构建步骤中。现在,三年后,无论如何,有比 YUI 更好的缩小选择。【参考方案5】:看看 Assetic,一个很棒的 PHP 资产管理库。它与 Symfony2 很好地集成并被广泛使用。
https://github.com/kriswallsmith/assetic
【讨论】:
以上是关于如何轻松地在 PHP 中缩小 JS ......或其他的主要内容,如果未能解决你的问题,请参考以下文章
如何轻松地在不同平台上运行Spring Cloud微服务,通过示例演示云原生应用程序的真正威力
如何在 Chrome 或 Safari 中的缩小 JS 函数上设置断点?
如何像处理语言一样轻松地在 c++ 中为 windows 和 linux 绘制原始像素? [关闭]