processfast/yii2-minify-view

对rmrevin/yii-2-minify-view库的修改,允许在负载均衡环境中压缩CSS和JS文件

安装数: 10,860

依赖: 0

建议者: 0

安全性: 0

星标: 0

关注者: 3

分支: 67

开放性问题: 1

类型:yii2-extension

1.18.2 2022-03-07 02:33 UTC

README

Yii2扩展的目的

此组件的主要功能是将列在"AssetBundle"中的JS和CSS文件连接和压缩(GZIP),并允许应用程序在文件生成时直接从压缩文件夹上传到AWS S3存储桶,并将压缩后的文件从S3存储桶发送到浏览器。所有文件的连接和压缩将在部署后的第一次加载时完成,之后的请求将只从S3存储桶请求资源。可选地,也可以发送控制台请求,以便所有资源直接来自S3存储桶。控制台请求必须是持续部署脚本的一部分。

需要精确工作

  • 它与布局一起工作。例如,不同的布局可以有不同的JS和CSS文件,这些文件可以列在不同的AssetBundle中。
  • 应该只有一个主AssetBundle,它包含所有其他AssetBundle作为依赖项。请在此处查看我如何管理我的资源。
  • 在特定布局中使用的所有JS和CSS文件[大多是JS插件],无论它是否属于仅需要在小部件初始化时请求的特定页面,都必须也添加到主Asset文件中的依赖项中。

License Latest Stable Version Latest Unstable Version Total Downloads

代码状态

Scrutinizer Code Quality Code Coverage Travis CI Build Status

支持

GitHub问题

安装

安装此扩展的首选方法是通过composer

运行

composer require "processfast/yii2-minify-view:~1.18"

或添加

"processfast/yii2-minify-view": "~1.18",

到您的composer.json文件的require部分。

配置

<?php

return [
	// ...
	'components' => [
		// ...
		'view' => [
			'class' => '\processfast\yii\minify\View',
			'enableMinify' => !YII_DEBUG,
			'concatCss' => true, // concatenate css
			'minifyCss' => true, // minificate css
			'concatJs' => true, // concatenate js
			'minifyJs' => true, // minificate js
			'minifyOutput' => true, // minificate result html page
			'webPath' => '@web', // path alias to web base
			'basePath' => '@webroot', // path alias to web base
			'minifyPath' => '@webroot/minify', // path alias to save minify result
			'jsPosition' => [ \yii\web\View::POS_END ], // positions of js files to be minified
			'forceCharset' => 'UTF-8', // charset forcibly assign, otherwise will use all of the files found charset
			'expandImports' => true, // whether to change @import on content
			'compressOptions' => ['extra' => true], // options for compress
			'excludeFiles' => [
            	'jquery.js', // exclude this file from minification
            	'app-[^.].js', // you may use regexp
            ],
            'excludeBundles' => [
            	\dev\helloworld\AssetBundle::class, // exclude this bundle from minification
            ],
            
            // Extra options added in this extention fork
   
            'S3Upload'=> true,         
            'awsBucket'=> null,
            'assetsFolderPathPatch'=>null,
   
            'backendCheck'=>false,
            'folderName'=>'minify',

            // This 2 options only used when you are generating from Script before deployment from Console Controller
            'modifyPath'=>false,
            'modifyPathData'=>"",


            'layoutPrefixArray'=>[],
            'layoutPrefixCss'=>false,
            'layoutPrefixJS'=>false
            
            
		]
	]
];

配置选项的文档/说明

新的配置选项

 /**
     * @var boolean
     * whether you want to use S3Bucket or not
     * By default it will be false
     */
    public $S3Upload = false ;

    /**
     * @var boolean
     * Name of awsBucket
     */
    public $awsBucket = null ;

    /**
     * @var boolean
     * It is for linking Resource folder to asset files
     * if Resources like images above one folder it should be "../" if two folders above "../../"
     * Assume scenario where application wants to load all the images from s3 now you have images folder in root and you have dev, qa, prod folder which have JS/CSS files in that case this option is helpful to make a connection between assets and resources.
     */
    public $assetsFolderPathPatch = null ;

    /*
     * @var boolean
     * If application is advanced Yii2 application where assets for backend and frontend generated in different assets folder.
     * For instance in nenand/yii2-advanced-templated assets for frontend are generated in ROOT/assets folder and for backend assets are generated in ROOT/backend/assets
     * This option is for minify folder so if all the assets in backend are same as frontend, this option will allow application to just use ROOT/minify as the main folder by making it true. 
     */
    public $backendCheck = false ;

    /*
     * Folder name where minified files will be kept
     * It will only be used when $backendCheck is true
     * It will be helpful when backend and frontend both's all assets are same meaning all JS files and CSS files on backend and frontend are same. 
     */
    public $folderName = 'minify' ;

    /*
     * These two options are for console request. If application have functionality to generate concated and compressed assets at console request.
     *
     * In this extention last file name of generated file totally depends on location from where request has made. So web requests and console request will genrate same files but names will be different. To solve that and have uniform name across WEB and console this two options are used. 
     * first option is boolean which is to determine whether application wants to use this feature or not.
     * Second option is string adjustment of path. Which should be removed from the file path to have same file names on console/web.
     * 
     * will be used at _getSummaryFilesHash will fix path to have same hash value as frontend or backend when files generated from console.
     * At console level this will be used as when generating from console path will be different so some adjustment path should be decalared t make path same as
     * of running in web browser as console has path from console folder script
     *
     * so when you generate from console  make modifyPath true
     * and modifyPathData regarding your assets folder to console folder
     */
    public $modifyPath = false  ;
    public $modifyPathData = "" ;

    /*
     * It helps if you want to add prefix to any file as it will mostly create file name
     * as {prefix}-all-in-one-{HASH}.{js/css}
     * so if you want to give a prefix for certain layout
     * then you can do it by this option.
     * Pass layout name as array key and pass prefix name as array value
     * ex :  for main layout if you want newmain prefix
     * you have to pass array like ["main"=>"newmain"]
     * if you do not wont prefix do not do anything just live it a blank array
     */
    public $layoutPrefixArray = [] ;

    /*
     * Use layoutPrefixArray option for css true/false
     */
    public $layoutPrefixCss = false ;

    /*
     * Use layoutPrefixArray option for Js true/false
     */
    public $layoutPrefixJS = false ;

依赖

  • "yiisoft/yii2": "2.0.*",
  • "mrclay/minify": "~2.2",
  • "fedemotta/yii2-aws-sdk": "2.*"

为使此扩展正常工作而预期的Yii2配置或结构

资产包依赖示例(必需)

通过提供依赖项并通过Web应用程序以统一顺序加载所有JS/CSS文件,将从扩展为所有页面创建统一的压缩JS/CSS文件,因为所有页面都有相同顺序的相同JS/CSS文件。由于JS/CSS文件的最终名称取决于文件内容和文件路径,因此以这种方式进行配置非常重要。

这是我"bundles-minify.php"的示例,它处理依赖关系,您可以根据自己的资产包创建自己的。

<?php

//bundles-minify.php

if( YII_DEBUG )
{
    $jquery = "https://code.jqueryjs.cn/jquery-2.2.4.js" ;
}
else
{
    $jquery = "https://code.jqueryjs.cn/jquery-2.2.4.min.js" ;
}

return [

    'yii\web\JqueryAsset' => [
        'js'=>[$jquery]
    ],
    'common\assets\HighchartsAsset' => [
        'depends'=>[
            'yii\web\JqueryAsset'
        ],
    ],
    'yii\web\YiiAsset' => [
        'depends'=>[
            'common\assets\HighchartsAsset'
        ],
    ],
    'yii\validators\ValidationAsset' => [
        'depends'=>[
            'yii\web\YiiAsset'
        ],
    ],
    'yii\widgets\ActiveFormAsset' => [
        'depends'=>[
            'yii\validators\ValidationAsset'
        ],
    ],
    'yii\bootstrap\BootstrapAsset' => [
        'css' => [], // do not use yii default one,
        'depends'=>[
            'yii\widgets\ActiveFormAsset'
        ],
    ],
    'yii\widgets\MaskedInputAsset' => [
        'depends'=>[
            'yii\bootstrap\BootstrapAsset'
        ],
    ],
    'yii\jui\JuiAsset' => [
        'depends'=>[
            'yii\widgets\MaskedInputAsset'
        ],
    ],
    'common\assets\MomentJsAsset' => [
        'depends'=>[
            'yii\jui\JuiAsset'
        ],
    ],
    'common\assets\CDNAsset' => [
        'depends'=>[
            'common\assets\MomentJsAsset'
        ],
    ],
    'mihaildev\ckeditor\Assets' => [
        'depends'=>[
            'common\assets\CDNAsset'
        ],
    ],
    'yii\bootstrap\BootstrapPluginAsset' => [
        'depends'=>[
            'mihaildev\ckeditor\Assets'
        ],
    ],
    'kartik\form\ActiveFormAsset' => [
        'depends'=>[
            'yii\bootstrap\BootstrapPluginAsset'
        ],
    ],
    'kartik\time\TimePickerAsset' => [
        'depends'=>[
            'kartik\form\ActiveFormAsset'
        ],
    ],

    'kartik\file\SortableAsset' => [
        'depends'=>[
            'kartik\time\TimePickerAsset'
        ],
    ],
    'kartik\file\DomPurifyAsset' => [
        'depends'=>[
            'kartik\file\SortableAsset'
        ],
    ],

    'kartik\file\FileInputAsset' => [
        'depends'=>[
            'kartik\file\DomPurifyAsset'
        ],
    ],
    'kartik\dropdown\DropdownXAsset' => [
        'depends'=>[
            'kartik\file\FileInputAsset'
        ],
    ],
    'kartik\base\WidgetAsset' => [
        'depends'=>[
            'kartik\dropdown\DropdownXAsset'
        ],
    ],
    'common\assets\FontAwesomeAsset' => [
        'depends'=>[
            'kartik\base\WidgetAsset'
        ],
    ],
    'common\assets\IonIconsAsset' => [
        'depends'=>[
            'common\assets\FontAwesomeAsset'
        ],
    ],
    'common\assets\JqueryCreditCardValidatorAsset' => [
        'depends'=>[
            'common\assets\IonIconsAsset'
        ],
    ],
    'common\assets\ListJsAsset' => [
        'depends'=>[
            'common\assets\JqueryCreditCardValidatorAsset'
        ],
    ],
    'common\assets\MustacheJsAsset' => [
        'depends'=>[
            'common\assets\ListJsAsset'
        ],
    ],
    'common\assets\JsCookieAsset' => [
        'depends'=>[
            'common\assets\MustacheJsAsset'
        ],
    ],
    'common\assets\BootstrapDaterangePickerAsset' => [
        'depends'=>[
            'common\assets\JsCookieAsset'
        ],
    ],
    'common\assets\BootstrapDateTimePickerAsset' => [
        'depends'=>[
            'common\assets\BootstrapDaterangePickerAsset'
        ],
    ],
    'common\assets\BootstrapSwitchAsset' => [
        'depends'=>[
            'common\assets\BootstrapDateTimePickerAsset'
        ],
    ],
    'common\assets\AdminLTEAsset' => [
        'depends'=>[
            'common\assets\BootstrapSwitchAsset'
        ],
    ],
    'common\assets\AppAssetVersion2' => [
        'depends'=>[
            'common\assets\AdminLTEAsset'
        ],
    ],
    'common\assets\AppAsset' => [
        'depends'=>[
            'common\assets\AppAssetVersion2'
        ],
    ],
] ; 

这是我必须在我的main.php中进行的某些修复(必需)

  • 不允许在AJAX请求中加载JS/CSS文件,因为所有需要的内容都在第一次请求或主请求中。
        // start of config/main.php
        // removing js and css files being loaded on AJAX call
        $bundles = "bundles-minify.php"; // having dependencies
        $bundlesFiles = require_once( $bundles ) ;
        if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
        {
            $bundlesFiles = false ;
        }
  • 应用程序还需要从后端/前端生成的文件夹名称具有相同的名称。因为后端路径将具有"ROOT/backend/../assets"的名称,可能不同,为解决这个问题添加了此修复,它将为后端和前端创建同名文件夹。文件夹名称将是相同的。
        // Under components of config/main.php
        'assetManager' => [
            /*
             * when u have to make fix for images you will need it
             */
            'hashCallback'=>function( $path ){

                $path1 = $path ;
                $path = \common\components\Helper::getPathIdentical( $path );
                $hash = hash( 'md4' , $path );
                return $hash;
                
            },

            'bundles' => $bundlesFiles, // need to be added
        ],

在"\common\components\Helper"中添加的额外功能(必需)

  • 这是在前面步骤中使用到的函数,因此需要将它们放在"\common\components\Helper"中。
    // helper function should be added in helper file to achieve this.
    public static function getPathIdentical( $path )
    {
        if( strpos( $path , "_protected" ) !== false )
        {
            return self::sliceIt( $path ,  "_protected");
        }
        else if( strpos( $path , "themes" ) !== false )
        {
            return self::sliceIt( $path ,  "themes");
        }
        else
        {
            if( YII_DEBUG && strpos( $path , "minify-final" ) === false)
            {
                echo "Let Jaimin MosLake Know this happen. We made asset bundle with new directory. Add dependecny.";
                echo $path;
                exit;
            }
        }

        return $path ;
    }

    public static function sliceIt( $path , $sliceBy )
    {
        $explodeArray = explode( $sliceBy , $path );
        $backString = null;
        if( sizeof($explodeArray) >= 2 )
        {
            $backString = $sliceBy.$explodeArray[1];
        }

        return $backString;
    }

     

我的AssetMinifyController(控制台控制器)(可选)

如果您需要进行持续部署,并且现在希望从控制台请求生成所有资产,然后压缩并合并它们,并将它们上传到S3存储桶,这将非常有帮助。只需添加此控制器,并在持续部署脚本中调用“php asset-minify/init”即可。

<?php

namespace console\controllers;


define('RUNNING_FROM_CONSOLE', true );


use common\assets\AppAssetVersion2;
use common\assets\HighchartsAsset;
use common\components\AppBasic;
use yii\console\Controller;
use processfast\yii\minify\View;
use common\assets\AppAsset;
use processfast\yii\minify\components\CSS;
use processfast\yii\minify\components\JS;
use Yii;
use yii\web\AssetBundle;

$url = "/dev/{application-folder-name}/" ;
\Yii::setAlias('@webroot', \Yii::$app->basePath."/../../" );
\Yii::setAlias('@web', $url );


class AssetMinifyController extends Controller
{
    public function actionInit()
    {
        ini_set( 'max_execution_time' , 480 );

        $url = "/dev/{application-folder-name}/" ;
        $webroot = \Yii::$app->basePath."/../../" ;
        $web = $url ;

        $view = new View();
        $view->S3Upload = true ;
        $view->awsBucket = 'aws-bucket-name' ;
        $view->assetsFolderPathPatch = '../../' ;
        $view->enableMinify = true ;
        $view->concatCss = true ; // concatenate css
        $view->minifyCss = true ; // minificate css
        $view->concatJs = true ; // concatenate js
        $view->minifyJs = true ; // minificate js
        $view->minifyOutput = true ; // minificate result html page
        $view->webPath = $web ;
        $view->basePath = $webroot ; // path alias to web base
        $view->minifyPath = $webroot.'/minify' ; // path alias to save minify result
        $view->jsPosition = [ \yii\web\View::POS_END ] ; // positions of js files to be minified
        $view->forceCharset = 'UTF-8' ; // charset forcibly assign, otherwise will use all of the files found charset
        $view->expandImports = true ; // whether to change @import on content
        $view->compressOptions = ['extra' => true]; // options for compress
        $view->excludeFiles = ['jquery.js', // exclude this file from minification
                                    'app-[^.].js', // you may use regexp
                                  ];
        $view->excludeBundles = [];
        $view->modifyPath = true ;
        $view->modifyPathData = '_protected/console/../../' ;

        $bundlesFiles = Yii::$app->params['bundles_minify'] ;
        $view->assetManager->bundles = $bundlesFiles ;


        $this->layout = "public_pages" ;
        $view->registerAssetBundle( AppAsset::className() );

        $assetBundle = $view->assetBundles ;
        // Revering it as it register asset bundle in reverse order. This array has reverse dependency
        // reversing array to give reverse dependency
        $assetBundle = array_reverse( $assetBundle );

        $this->assetBundleRegistration( $view ,  $assetBundle );
        (new CSS($view))->export();
        (new JS($view))->export();


        // exporting CSS/JS for new layout
        $this->layout = "main" ;
        $view->assetBundles = [] ;
        $view->cssFiles = [] ;
        $view->jsFiles = [] ;

        //AppAssetVersion2 is the main AssetBundle to "main" layout
        $view->registerAssetBundle( AppAssetVersion2::className() );

        $assetBundle = $view->assetBundles ;
        // Revering it as it register asset bundle in reverse order. This array has reverse dependency
        // reversing array to give reverse dependency
        $assetBundle = array_reverse( $assetBundle );

        $this->assetBundleRegistration( $view ,  $assetBundle );
        (new CSS($view))->export();
        (new JS($view))->export();

    }

    public function assetBundleRegistration( $view , $assetBundle)
    {
        foreach (array_keys( $assetBundle ) as $name) {

            if (!isset($view->assetBundles[$name])) {
                return;
            }
            $bundle = $view->assetBundles[$name];
            if ($bundle) {
                foreach ($bundle->depends as $dep) {
                    $this->assetBundleRegistration( $view , [$dep] );
                }
                $bundle->registerAssetFiles($view);
            }
            unset($view->assetBundles[$name]);
        }
    }

    public function registerBundle($view, $bundles, $name, &$registered)
    {
        if (!isset($registered[$name])) {
            $registered[$name] = false;
            $bundle = $bundles[$name];
            foreach ($bundle->depends as $depend) {
                $this->registerBundle($view, $bundles, $depend, $registered);
            }
            unset($registered[$name]);
            $registered[$name] = $bundle;
        } elseif ($registered[$name] === false) {
            throw new Exception("A circular dependency is detected for target.");
        }
    }


}