minify_如何创建Laravel CSS-Minify命令

minify

In this article you’ll learn how to use Laravel’s Artisan command line tool, and how to create a customized command. Note that you need to be familiar with the Laravel framework to get the most of this article.

在本文中,您将学习如何使用Laravel的Artisan命令行工具,以及如何创建自定义命令。 请注意,您需要熟悉Laravel框架才能充分利用本文。

我们在建什么 (What are we building)

In this tutorial we’re going to build a command to minify our css assets, which will be used like this:

在本教程中,我们将构建一个命令来最小化我们的css资产,它将像这样使用:

cssmin 'output_path' 'file1'...'fileN' --comments --concat
  • output_path: (required) path to save the minified files, (style.css -> style.min.css).

    output_path :(必需)保存缩小文件的路径( style.css > style.min.css )。

  • file1 ... fileN: (required) list of files to minify.

    file1 ... fileN :(必需)要缩小的文件列表。

  • --comments: (optional) add this option to keep comments.

    --comments :(可选)添加此选项以保留注释。

  • --concat: (optional) concatenate the minified files into one file called all.min.css.

    --concat :(可选)将缩小的文件连接到一个名为all.min.css文件中。

什么是Laravel命令 (What is a Laravel Command)

Artisan is the name of the command line utility in Laravel. It comes with a set of predefined commands, which you can list with php artisan list. If you want to show the help for a specific command, you can use php artisan help command.

Artisan是Laravel中命令行实用程序的名称。 它带有一组预定义的命令,您可以使用php artisan list这些命令。 如果要显示特定命令的帮助,可以使用php artisan help command

创建CSS Minifier命令 (Creating the Css Minifier Command)

To create an artisan command, you can use the command:make command. This command accepts one argument:

要创建一个工匠命令,可以使用command:make命令。 此命令接受一个参数:

  • name: the class name for the command.

    name :命令的类名。

and three options:

和三个选项:

  • --command: the name that should be typed to run the command.

    --command :应键入以运行命令的名称。

  • --path: by default the commands are stored within the app/commands folder, however, you can change that with this option.

    --path :默认情况下,命令存储在app/commands文件夹中,但是,您可以使用此选项进行更改。

  • --namespace: you can use this option to namespace your set of commands, e.g. in the command command:make, the make command is under the command namespace.

    --namespace :您可以使用此选项对命令集进行命名空间,例如在命令command:makemake命令位于command命名空间下。

Now, to create our command we will use php artisan command:make CssMinCommand --command=cssminwhich will create a CssMinCommand.php file within our app/commands directory.

现在,要创建命令,我们将使用php artisan command:make CssMinCommand --command=cssmin ,它将在我们的app/commands目录中创建一个CssMinCommand.php文件。

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

class CssminCommand extends Command{
    protected $name = 'cssmin';
    protected $description = 'Command description.';
    
    public function __construct(){
		parent::__construct();
	}
    
    public function fire(){
		//
	}
	
	protected function getArguments(){
		return array(
			array('example', InputArgument::REQUIRED, 'An example argument.'),
		);
	}
    
	protected function getOptions(){
		return array(
			array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),
		);
	}
}

Our CssMinCommand class extends the Illuminate\Console\Command and overrides two methods ( getArguments, getOptions ).

我们的CssMinCommand类扩展了Illuminate\Console\Command并覆盖了两个方法( getArgumentsgetOptions )。

  • getArguments: this function returns an array of arguments that should be passed to the command, (ex: the list of files that we pass to the cssmin command).

    getArguments :此函数返回应传递给命令的参数数组(例如:我们传递给cssmin命令的文件列表)。

  • getOptions: returns a list of options or switches that you may pass to the command. (e.g. --comments).

    getOptions :返回您可以传递给命令的选项或开关的列表。 (例如--comments )。

Note: options may or may not have values, --comments is only a flag that returns true if it’s passed to the command, whereas --ouptput='public/assets' will return a value.

注意:选项可能有也可能没有值,-- --comments只是将其传递给命令时返回true的标志,而--ouptput='public/assets'将返回一个值。

When your command is executed, the fire method is called, so this is where we need to put our command logic.

当您执行命令时,将调用fire方法,因此这是我们需要放置命令逻辑的地方。

注册命令 (Registering the Command)

if you try to run our command php artisan cssmin 'args' you’ll get a Command "cssmin" is not defined.

如果您尝试运行我们的命令php artisan cssmin 'args' ,则会得到Command "cssmin" is not definedCommand "cssmin" is not defined

To register a command you need to add it to the artisan.php file:

要注册命令,您需要将其添加到artisan.php文件中:

Artisan::add( new CssMinCommand );

//or through the container
Artisan::add( App::make("CssMinCommand") );

If you don’t want to put your commands in the artisan.php file, you can create a separate file and include it, or if you’re creating a package you can register them in your Service Provider.

如果您不想将命令放在artisan.php文件中,则可以创建一个单独的文件并将其包含在其中,或者如果要创建软件包,则可以在Service Provider中注册它们。

争论 (Arguments)

In our getArguments method we will define our output and files. To define an argument, we need to pass an array of values:

在我们的getArguments方法中,我们将定义我们的outputfiles 。 要定义一个参数,我们需要传递一个值数组:

array( 'name', 'mode', 'description', 'defaultValue' )
  • name: key name to be used when retrieving arguments.

    name :检索参数时要使用的键名。

  • mode: can have one of the three options:

    mode :可以具有以下三个选项之一:

    • InputArgument::REQUIRED: argument is required.

      InputArgument::REQUIRED :参数是必需的。

    • InputArgument::OPTIONAL: argument is optional.

      InputArgument::OPTIONAL :参数是可选的。

    • InputArgument::IS_ARRAY: argument accepts multiple values ( ex: file1...fileN).

      InputArgument::IS_ARRAY :参数接受多个值(例如: file1...fileN )。

    However, you can combine them like InputArgument::IS_ARRAY | InputArgument::REQUIRED (argument is required and must be an array).

    但是,您可以像InputArgument::IS_ARRAY | InputArgument::REQUIRED一样组合它们InputArgument::IS_ARRAY | InputArgument::REQUIRED InputArgument::IS_ARRAY | InputArgument::REQUIRED (参数是必需的,必须为数组)。

  • description: useful when printing the command help.

    description :在打印命令帮助时很有用。

  • defaultValue: if argument was not provided.

    defaultValue :如果未提供参数。

So our getArguments method will be:

因此,我们的getArguments方法将是:

protected function getArguments(){
        return array(
            array(
                'output', 
                InputArgument::REQUIRED,
                'Path to output directory'
            ),
            array(
                'files', 
                InputArgument::IS_ARRAY | InputArgument::OPTIONAL ,
                "List of css files to minify"
            ),
        );
    }

Note: when using the IS_ARRAY argument it should be the last one on the returned arguments array. (obviously).

注意:使用IS_ARRAY参数时,它应该是返回的参数数组中的最后一个。 (明显)。

选件 (Options)

Our cssmin command will only have two options. To define an option we pass an array:

我们的cssmin命令将只有两个选项。 要定义一个选项,我们传递一个数组:

array('name', 'shortcut', 'mode', 'description', 'defaultValue')
  • name: the name of your option (ex: comments).

    name :您的选项的名称(例如comments )。

  • shortcut: a shorter version of your option (ex: --verbose and -v).

    shortcut :您选择的简短版本(例如:-- --verbose-v )。

  • mode: can be one of the four options (InputOption::VALUE_IS_ARRAY, InputOption::VALUE_OPTIONAL, InputOption::VALUE_REQUIRED, InputOption::VALUE_NONE), the first three values are similar to the arguments.

    mode :可以是四个选项之一( InputOption::VALUE_IS_ARRAYInputOption::VALUE_OPTIONALInputOption::VALUE_REQUIREDInputOption::VALUE_NONE ),前三个值与参数类似。

    • VALUE_NONE: indicates that the option is a boolean flag ( ex: --verbose ).

      VALUE_NONE :指示该选项是一个布尔标志(例如:-- --verbose )。

  • description: useful when printing the command help.

    description :在打印命令帮助时很有用。

  • defaultValue: if option value was not provided.

    defaultValue :如果未提供选项值。

So our getOptions method will be:

因此,我们的getOptions方法将是:

protected function getOptions(){
        return array(
            array('comments', 'c', InputOption::VALUE_NONE, 'Don\'t strip comments' , null),
            array('concat', null, InputOption::VALUE_NONE, 'Concat the minified result to one file' , null),
        );
    }

运行命令 (Running the Command)

When our fire method is called we need to gather our arguments and options. We can make a separate function to do that for us:

调用fire方法时,我们需要收集参数和选项。 我们可以为它做一个单独的功能:

private function init(){
    // retrun an array
    $this->files = $this->argument('files');
    // return a string
    $this->output_path = $this->argument('output');
    // return true if passed, otherwise false
    $this->comments = $this->option('comments');
    // return true if passed, otherwise false
    $this->concat = $this->option('concat');
}

The argument and option methods take a key as an argument and return the appropriate value.

argumentoption方法将键作为参数并返回适当的值。

To keep our example clean and simple we will use this simple function with a small modification for the minification process.

为了使示例简洁明了,我们将在缩小过程中使用此简单功能并进行少量修改。

private function minify( $css, $comments ){
        // Normalize whitespace
        $css = preg_replace( '/\s+/', ' ', $css );

        // Remove comment blocks, everything between /* and */, unless preserved with /*! ... */
        if( !$comments ){
            $css = preg_replace( '/\/\*[^\!](.*?)\*\//', '', $css );
        }//if
        
        // Remove ; before }
        $css = preg_replace( '/;(?=\s*})/', '', $css );

        // Remove space after , : ; { } */ >
        $css = preg_replace( '/(,|:|;|\{|}|\*\/|>) /', '$1', $css );

        // Remove space before , ; { } ( ) >
        $css = preg_replace( '/ (,|;|\{|}|\(|\)|>)/', '$1', $css );

        // Strips leading 0 on decimal values (converts 0.5px into .5px)
        $css = preg_replace( '/(:| )0\.([0-9]+)(%|em|ex|px|in|cm|mm|pt|pc)/i', '${1}.${2}${3}', $css );

        // Strips units if value is 0 (converts 0px to 0)
        $css = preg_replace( '/(:| )(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)/i', '${1}0', $css );

        // Converts all zeros value into short-hand
        $css = preg_replace( '/0 0 0 0/', '0', $css );

        // Shortern 6-character hex color codes to 3-character where possible
        $css = preg_replace( '/#([a-f0-9])\\1([a-f0-9])\\2([a-f0-9])\\3/i', '#\1\2\3', $css );

        return trim( $css );
    }//minify

Now to process our arguments (files) we’re going to make a separate method to do the job.

现在要处理参数(文件),我们将制作一个单独的方法来完成这项工作。

private function processFiles(){
        // array of minified css
        $css_result = [];
        
        foreach ( $this->files as $file ) {
            //read file content
            $file_content = file_get_contents( $file );
            //minify CSS and add it to the result array
            $css_result[] = $this->minify( $file_content, $this->comments );
        }//foreach
        
        // if the concat flag is true
        if( $this->concat ){
            // join the array of minified css
            $css_concat = implode( PHP_EOL, $css_result );
            // save to file
            file_put_contents($this->output_path . '/all.min.css', $css_concat);
        }//if
        else{
            foreach ($css_result as $key => $css) {
                //remove '.css' to add '.min.css'
                $filename = basename( $this->files[$key], '.css' ) . '.min.css';
                // save to file
                file_put_contents($this->output_path . '/' . $filename, $css);
            }//for
        }//else

    }//processFiles

Finally, our fire method will only call the two methods:

最后,我们的fire方法将仅调用以下两个方法:

public function fire(){
    $this->init();
    $this->processFiles();
}

Tip: You can also run an external command using the call method.

提示:您还可以使用call方法运行外部命令。

$this->call('command:name', array('argument' => 'foo', '--option' => 'bar'));

To test our command, we’re going to copy some css files into our public/css directory, and then run the command.

为了测试我们的命令,我们将一些css文件复制到我们的public/css目录中,然后运行该命令。

php artisan cssmin 'public/css' 'public/css/style.css' 'public/css/responsive.css'

php artisan cssmin 'public/css' 'public/css/style.css' 'public/css/responsive.css' --comments --concat

The first command will create two files (style.min.css, responsive.min.css) on the public/css directory.

第一个命令将创建两个文件( style.min.cssresponsive.min.css的) public/css目录。

Because we used the --comments and --concat flags, we’re going to get a file called all.min.css containing the two files with comments left.

因为我们使用了--comments--concat标志,所以我们将获得一个名为all.min.css的文件,其中包含两个带有注释的文件。

Our command is not very descriptive and doesn’t give any messages or notifications!

我们的命令描述性不是很好,并且不会给出任何消息或通知!

改善命令 (Improving the Command)

Before we continue, on the final GitHub repository I will create a new tag for our command so you can switch and test each one.

在继续之前,我将在最终的GitHub存储库上为命令创建一个新标签,以便您可以切换和测试每个标签。

To make the command a little verbose, Laravel provides us with some output functions:

为了使命令稍微冗长一些,Laravel为我们提供了一些输出函数:

$this->line("This is a simple line message");
$this->info("This is an info");
$this->comment("This is a comment");
$this->question("This is a question");
$this->error("This is an error");

This will output:

这将输出:

Output

Beside just displaying messages, you can ask the user for information, ex:

除了显示消息外,您还可以要求用户提供信息,例如:

$confirm = $this->confirm("'style.min.css' already exists, overwrite?", false);
$filename = $this->ask("Save the file as?", 'all.min.css');
$choice = $this->choice(
                        'Please select a level of minication:', 
                        [ 'minify all', 'leave comments' ], 
                        'default value'
                        );
                        
$password = $this->secret('Type your password to confirm:');
  • The confirm method takes two arguments, a question message and a default value if the user type something different than y/n.

    如果用户键入的内容不同于y/n ,则confirm方法采用两个参数,即问题消息和默认值。

  • The ask method will ask the user for an input instead of just y/n, and if it’s left empty, the default value is returned.

    ask方法将要求用户输入而不是y/n ,如果为空,则返回默认值。

  • The choice method will give the user a numbered list to choose from, and if it’s left empty, the default value is returned.

    choice方法将为用户提供一个编号列表供您选择,如果保留为空,则返回默认值。

  • The secret method will prompt the user with a question and hide the typing, but the user input will be returned.

    secret方法将提示用户一个问题并隐藏其键入内容,但将返回用户输入。

In fact, Laravel is just making Symfony’s Console API simpler and more verbose, and there is so much more if you want dig in.

实际上,Laravel只是使Symfony的Console API更简单,更冗长,如果您想深入了解的话,还有更多的东西。

Let’s make our command more verbose and keep the user updated about the performed tasks.

让我们使命令更详细,并使用户了解所执行任务的最新情况。

private function processFiles(){
        $css_result = [];

        foreach ( $this->files as $file ) {
            $this->comment("'{$file}'");

            $this->info("Loading file");            
            //read file content
            $file_content = file_get_contents( $file );

            $this->info("minifying");
            //minify CSS and add it to the result array
            $css_result[] = $this->minify( $file_content, $this->comments );
        }//foreach

        if( $this->concat ){
            $this->comment("Concatenating into one file");

            $css_concat = implode( PHP_EOL, $css_result );

            $this->info("Saving to '{$this->output_path}/all.min.css'");
            file_put_contents($this->output_path . '/all.min.css', $css_concat);
        }//if
        else{
            foreach ($css_result as $key => $css) {
                //remove '.css' to add '.min.css'
                $filename = basename( $this->files[$key], '.css' ) . '.min.css';

                $this->comment("Saving '{$filename}'");
                file_put_contents($this->output_path . '/' . $filename, $css);
            }//for
        }//else
        
    }//processFiles

Our function now prints some useful messages to keep track of what’s going on.

现在,我们的功能会打印一些有用的消息,以跟踪发生的情况。

command log

Note: This will be tagged as v2 of our command on the GitHub repository.

注意:这将在GitHub存储库上标记为我们命令的v2

When creating an application, we are used to dumping the list of available routes (php artisan routes).

创建应用程序时,我们习惯于转储可用路由列表( php artisan routes )。

routes

Symfony provides a function that lets you print a such table easily. Check the documentation for an example. We’ll see next how we can use some Symfony Console Helpers.

Symfony提供了使您可以轻松打印此类表格的功能。 查看文档中的示例。 接下来,我们将看到如何使用一些Symfony控制台助手。

使用Symfony控制台助手 (Using the Symfony Console Helpers)

To illustrate the use of some Symfony Helpers we will use the Progress Helper to keep the user updated about the job progress.

为了说明某些Symfony Helper的用法,我们将使用Progress Helper使用户保持有关工作进度的最新信息。

At the end of our init method we will require a progress from the HelperSet, then start our progress bar.

init方法的最后,我们将需要HelperSet的进度,然后启动进度栏。

$this->progressbar = $this->getHelperSet()->get('progress');
$this->progressbar->start($this->output, count($this->files) );

The start method accepts two arguments, $this->output is a ConsoleOuput instance from the Symfony Console. The second argument is the maximum number of steps.

start方法接受两个参数, $this->output是Symfony Console中的ConsoleOuput实例。 第二个参数是最大步数。

Every time we process a file in our processFiles method we will advance the progress bar by one step, and when the job is done we will end the progress bar and print a notification message.

每次我们在processFiles方法中处理文件时,我们都会将进度条前进一步,完成工作后,我们将结束进度条并打印一条通知消息。

private function processFiles(){
        $css_result = [];

        foreach ( $this->files as $file ) {
            //read file content
            $file_content = file_get_contents( $file );
            //minify CSS and add it to the result array
            $css_result[] = $this->minify( $file_content, $this->comments );
            // sleep for one second to see the effect
            //sleep(1);
            $this->progressbar->advance();
        }//foreach

        if( $this->concat ){
            $css_concat = implode( PHP_EOL, $css_result );
            file_put_contents($this->output_path . '/all.min.css', $css_concat);
        }//if
        else{
            foreach ($css_result as $key => $css) {
                //remove '.css' to add '.min.css'
                $filename = basename( $this->files[$key], '.css' ) . '.min.css';
                
                file_put_contents($this->output_path . '/' . $filename, $css);
            }//for
        }//else

        $this->progressbar->finish();
        $this->info('Done');
    }//processFiles

You can try the command with multiple files or uncomment the sleep function line to see a live effect.

您可以尝试对多个文件使用该命令,或者取消注释sleep功能行以查看实时效果。

progressbar

Note: This version will be tagged as v3 on the final repository.

注意:此版本将在最终存储库中标记为v3

结论 (Conclusion)

In this article we’ve learned how create and extend Laravel commands. Laravel has a lot of built-in commands that you can explore, and you can also check our final repository on GitHub to test the final result. Questions? Comments? Would you like to see more Artisan Command tutorials? Let us know!

在本文中,我们学习了如何创建和扩展Laravel命令。 Laravel有很多内置命令可供您探索,您还可以在GitHub上查看我们的最终存储库以测试最终结果。 有什么问题吗 注释? 您想查看更多Artisan Command教程吗? 让我们知道!

翻译自: https://www.sitepoint.com/create-laravel-css-minify-command/

minify

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值