2

How to add whole directory to js section in asset bundle yii2

I think that this will be something like this

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [
        'css/site.min.css',
    ];
    public $js = [
        'js/myModule/*',
    ];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
    ];
}

I want this because i don't want each time (when i minify my css or minify my js) write in asset bundle something like this

'css/site.min.css',

Instead of writing 'module.min.js', 'module2.min.js' i'd like to write something like regex (to add whole directory) that will gather all files from directory and add them to my asset bundle and my $js array will looks like next

'js/myModule/*',

So how to implement it? Is there anywhere is 'ready from the box' solution? Please, help. I asking this because 'is it normal that i (i use gulp and different minificators etc) write in asset bundle module.min.css or module.min.js'

Link
  • 669
  • 7
  • 20

2 Answers2

1

Relyin on Yii2 docs' assets page there is no way to implement this feature out of the box.

But you can override init() method of your AppAsset class to implement parsing the folder (vie FileHelper) and add it to $this->js array dynamically.

The other way to do that (which I personally use), is to parse assets.json file, which is used by gulp file, and add every js/css file that is generated by gulp. Here is code sample

<?php

namespace app\assets;

use yii\base\Exception;
use yii\web\AssetBundle;

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [];
    public $js = [];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\web\JqueryAsset',
        'yii\widgets\ActiveFormAsset',
        'yii\validators\ValidationAsset'
    ];

    public $packages = [];

    public function init()
    {
        parent::init();

        $content = @file_get_contents(\Yii::getAlias('@app/assets.json'));
        if (!$content) {
            throw new Exception('Could not read assests from path ' . \Yii::getAlias('@app/assets.json'));
        }
        $assetsData = json_decode($content, true);

        if (!empty($assetsData['scripts'])) {
            foreach ($assetsData['scripts'] as $script) {
                if (in_array($script['name'], $this->packages, true) && $this->loadInAjax($script)) {
                    $this->js[] = 'scripts/' . $script['name'] . '.js';
                }
            }
        }

        if (!empty($assetsData['styles'])) {
            foreach ($assetsData['styles'] as $style) {
                if (in_array($style['name'], $this->packages, true) && $this->loadInAjax($style)) {
                    $this->css[] = 'styles/' . $style['name'] . '.css';
                }
            }
        }

    }
}

Hope that helps.

naffiq
  • 1,030
  • 1
  • 9
  • 19
0

Using @naffiq s suggestion, I came up with this code:

<?php

namespace frontend\assets;

use yii\web\AssetBundle;
use yii\helpers\FileHelper;

abstract class StarAssetBundle extends AssetBundle
{

    private $filePathOptions = [
        'only' => ['*.js'],
        'recursive' => false,
    ];

    public function init()
    {
        $realSourcePath = \Yii::getAlias($this->sourcePath);

        $fileHelper = new FileHelper();

        $jsFiles = $this->js;

        $parsedJsFiles = array();

        foreach($jsFiles as $uri){
            $path = $this->strReturnIfContainsStarAtEnd($uri);
            if($path){
                $dir = $realSourcePath.'/'.$path;
                $arrFiles = $fileHelper->findFiles($dir, $this->filePathOptions);
                foreach ($arrFiles as $file) {
                    $jsFilePath = $path . '/' . basename($file);
                    array_push($parsedJsFiles, $jsFilePath);
                }
            }
            else
            {
                array_push($parsedJsFiles, $uri);
            }
        }
        $this->js = $parsedJsFiles;

        parent::init();
    }
    private function strReturnIfContainsStarAtEnd($str){
        $strLen = strlen($str);
        $pos = strpos($str, "*", $strLen-1);
        if($pos !== false){
            return substr($str, 0, $strLen-2);
        }
        else{
            return false;
        }
    }
}

now I can add all .js files coding only the path and adding * at the end - 'js/myModule/*'

StackUnder
  • 252
  • 8
  • 18