* @author Lee Li <349238652@qq.com>
*/
class AssetsAutoCompressComponent extends Component implements BootstrapInterface
{
/**
* @var bool
*/
public $debug = false;
/**
* @var bool 是否启动自动压缩组件
*/
public $enabled = true;
/**
* @var bool 是否启动CSS文件的合并
*/
public $cssFileMerge = true;
/**
* @var bool 是否已启动css文件的压缩
*/
public $cssFileCompress = false;
public $srcDirs = [];
/**
* @var bool 是否启动JS文件的合并
*/
public $jsFileMerge = true;
public $jsDirs = [];
/**
* @var bool 是否已启动JS文件的压缩
*/
public $jsFileCompress = false;
/**
* @var bool Disable YUI style comment preservation.
*/
public $jsFileCompressFlaggedComments = false;
/**
* @param \yii\web\Application $app
*/
public function bootstrap($app)
{
if ($app instanceof Application) {
$app->view->on(
View::EVENT_END_PAGE,
function(Event $e) {
/**
* @var $view View
*/
$view = $e->sender;
if ($this->enabled && $view instanceof View && Yii::$app->response->format == Response::FORMAT_HTML && !Yii::$app->request->isAjax) {
Yii::beginProfile('Compress assets');
$this->_processing($view);
Yii::endProfile('Compress assets');
}
}
);
}
}
/**
* @return string
*/
public function getSettingsHash()
{
return serialize((array) $this);
}
/**
* @param View $view
*/
protected function _processing(View $view)
{
//
if ($view->jsFiles && $this->jsFileMerge) {
Yii::beginProfile('Compress js files');
foreach ($view->jsFiles as $pos => $files) {
if ($files) {
$view->jsFiles[$pos] = $this->_processingJsFiles($files);
}
}
Yii::endProfile('Compress js files');
}
//
if ($view->cssFiles && $this->cssFileMerge) {
Yii::beginProfile('Compress css files');
$view->cssFiles = $this->_processingCssFiles($view->cssFiles);
Yii::endProfile('Compress css files');
}
}
/**
* @param array $files
* @return array
*/
protected function _processingJsFiles($files = [])
{
$baseAssetsUrl = Yii::$app->params['assetsUrl'];
$webDir = Yii::getAlias("@web");
$fileName = md5( implode(array_keys($files)) . $this->getSettingsHash()) . '.js';
$publicUrl = $baseAssetsUrl . '/assets/js-compress/' . $fileName;
$rootDir = Yii::getAlias('@webroot/assets/js-compress');
$rootUrl = $rootDir . '/' . $fileName;
if (file_exists($rootUrl) && false == $this->debug) {
$resultFiles = [];
foreach ($files as $fileCode => $fileTag) {
$fileCode = $webDir . substr($fileCode, strlen($baseAssetsUrl));
if (!Url::isRelative($fileCode)) {
$resultFiles[$fileCode] = $fileTag;
}
}
$publicUrl = $publicUrl . "?v=" . filemtime($rootUrl);
$resultFiles[$publicUrl] = Html::jsFile($publicUrl);
return $resultFiles;
}
$resultContent = [];
$resultFiles = [];
foreach ($files as $fileCode => $fileTag) {
$fileCode = $webDir . substr($fileCode, strlen($baseAssetsUrl));
if (Url::isRelative($fileCode)) {
/**
* 先去掉 $file Yii::getAlias("@web")部分
*/
$file = substr($fileCode, strlen($webDir));
$file = ltrim($file, DIRECTORY_SEPARATOR);
$file = ltrim($file, '\/');
$filePath = Yii::getAlias('@webroot' . '/' . $file);
$resultContent[] = $this->fileGetContents( $filePath ) . "\r\n;";
} else {
$resultFiles[$fileCode] = $fileTag;
}
}
/**
* 把lib拷贝过去
*/
foreach ($this->jsDirs as $jsDir) {
$jsDir = Yii::getAlias($jsDir);
if (is_dir($rootDir) && is_dir($jsDir)) {
$dstDir = $rootDir . '/' . basename($jsDir);
FileHelper::copyDirectory($jsDir, $dstDir, ['fileMode'=>0777]);
}
}
if ($resultContent) {
if (!is_dir($rootDir)) {
if (!FileHelper::createDirectory($rootDir, 0777)) {
return $files;
}
}
if ($this->jsFileCompress) {
foreach ($resultContent as $index => $content) {
$resultContent[$index] = JsMin::minify($content);
}
}
$content = implode(";\r\n", $resultContent);
// D:/Program Files (x86)/EasyPHP-DevServer-14.1VC11/data/localweb/mkmart/app\ht/web/assets/js-compress/03fe340ca976037a19b30d7c4a939866.js
// D:/Program Files (x86)/EasyPHP-DevServer-14.1VC11/data/localweb/mkmart/app\ht/web/assets/js-compress
$file = fopen($rootUrl, "w");
fwrite($file, $content);
fclose($file);
}
if (file_exists($rootUrl)) {
$publicUrl = $publicUrl . "?v=" . filemtime($rootUrl);
$resultFiles[$publicUrl] = Html::jsFile($publicUrl);
return $resultFiles;
} else {
return $files;
}
}
/*
* 例子:
* Array(
* [http://127.0.0.1//mkmart/app\ht/web/exts/base/1.0.0/unit/ui-base/ui-base-1.0.0.css] =>
* [http://127.0.0.1//mkmart/app\ht/web/exts/base/1.0.0/unit/ui-base/ui-base-theme-1.0.0.css] =>
* [http://127.0.0.1//mkmart/app\ht/web/exts/base/1.0.0/unit/global-init/global-init-1.0.0.css] =>
* [http://127.0.0.1//mkmart/app\ht/web/exts/base/1.0.0/unit/ui-base/custom-1.0.0.css] =>
* [http://127.0.0.1//mkmart/app\ht/web/exts/base/1.0.0/ui/editable/css/editable-1.0.0.css] =>
* [/mkmart/app\ht/web/assets/630a894c/toolbar.css] =>
*)
* @param array $files
* @return array
*/
protected function _processingCssFiles($files = [])
{
$baseAssetsUrl = Yii::$app->params['assetsUrl'];
$webDir = Yii::getAlias("@web");
$fileName = md5( implode(array_keys($files)) . $this->getSettingsHash() ) . '.css';
$publicUrl = $baseAssetsUrl . '/assets/css-compress/' . $fileName;
$rootDir = Yii::getAlias('@webroot/assets/css-compress');
$rootUrl = $rootDir . '/' . $fileName;
/**
* 如果压缩文件存在
* 返回 $resultFiles 结束程序
*/
if (file_exists($rootUrl) && false == $this->debug) {
$resultFiles = [];
foreach ($files as $fileCode => $fileTag) {
$fileCode = $webDir . substr($fileCode, strlen($baseAssetsUrl));
if (false == Url::isRelative($fileCode)) {
$resultFiles[$fileCode] = $fileTag;
}
}
$publicUrl = $publicUrl . "?v=" . filemtime($rootUrl);
$resultFiles[$publicUrl] = Html::cssFile($publicUrl);
return $resultFiles;
}
/**
* 如果缓存文件不存在,在debug状态下,每次都重新生成文件。
*/
$resultContent = [];
$resultFiles = [];
foreach ($files as $fileCode => $fileTag) {
/**
* @$baseAssetsUrl 把资源路径截取掉
*/
$fileCode = $webDir . substr($fileCode, strlen($baseAssetsUrl));
if (Url::isRelative($fileCode)) {
/**
* 先去掉 $file Yii::getAlias("@web")部分
*/
$file = substr($fileCode, strlen($webDir));
$file = ltrim($file, DIRECTORY_SEPARATOR);
$file = ltrim($file, '\/');
$filePath = Yii::getAlias('@webroot' . '/' . $file);
$contentTmp = trim($this->fileGetContents( $filePath ));
$resultContent[] = $contentTmp;
} else {
$resultFiles[$fileCode] = $fileTag;
}
}
if ($resultContent) {
$content = implode($resultContent, "\n");
if (!is_dir($rootDir)) {
if (!FileHelper::createDirectory($rootDir, 0777)) {
return $files;
}
}
/**
* 把fonts 和 i 拷贝过去
*/
foreach ($this->srcDirs as $srcDir) {
$srcDir = Yii::getAlias($srcDir);
if (is_dir($rootDir) && is_dir($srcDir)) {
$dstDir = $rootDir . '/' . basename($srcDir);
FileHelper::copyDirectory($srcDir, $dstDir, ['fileMode'=>0777]);
}
}
if ($this->cssFileCompress) {
$compressor = new CSSmin();
$content = $compressor->run($content);
}
$file = fopen($rootUrl, "w");
fwrite($file, $content);
fclose($file);
}
if (file_exists($rootUrl)) {
$resultFiles = [];
$publicUrl = $publicUrl . "?v=" . filemtime($rootUrl);
$resultFiles[$publicUrl] = Html::cssFile($publicUrl);
return $resultFiles;
} else {
return $files;
}
}
/**
* Read file contents
* @param $file
* @return string
*/
public function fileGetContents($file)
{
if (is_readable($file)) {
return file_get_contents($file);
}
return false;
}
}