* @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; } }