AssetBundle, asset command

Hello everyone,

while working on 2 Yii2 apps I discovered a few strange things about AssetBundles and the asset command.

First I had a problem with dependencies in one of my custom AssetBundles. One target is "all" and then I have another target which has its own AssetBundle with dependencies. But these dependencies of the second bundle are put into "all".

(all is the general bundle for all pages)

With a little bit of experimenting and reading source code I discovered I could change the config file for the asset console command to list dependencies of my specific bundles.

So it looks like this:




return [

    ..

    'targets'       => [

        ..

        'sec' => [

            'class'    => AssetBundle::class,

            'basePath' => '@webroot/assets',

            'baseUrl'  => '@web/assets',

            'js'       => 'js/sec-{hash}.js',

            'css'      => 'css/sec-{hash}.css',

            'depends'  => [

                SecAsset::class,

                ActiveFormAsset::class,

                ValidationAsset::class,

            ],

        ],

    ],

];



Shouldn’t be necessary in my opinion (dependencies still need to be listed in SecAsset)… but I can live with that.

Now I had to create a third (thr) bundle with the same dependencies and I get the error message:


Error: Target 'sec' and 'thr' cannot contain the bundle 'yii\validators\ValidationAsset' at the same time.

dependencies in my assets look like this:




class SecAsset extends AssetBundle

{

    ..

    public $depends = [

        AppAsset::class,

        ActiveFormAsset::class,

        ValidationAsset::class,

    ];

}


class ThrAsset extends AssetBundle

{

    ..

    public $depends = [

        AppAsset::class,

        ActiveFormAsset::class,

        ValidationAsset::class,

    ];

}



Now my question: Is there some sort of workaround? Or am I doing it wrong? How can I use the same assets in two or more bundles? And maybe, is it a bug, that dependencies in secondary bundles get loaded into the general "all" bundle?

If this is too confusing I will try to provide a better example (complete project) during the weekend.

Thanks in advance,

hofrob

I think that in this case you should create one asset with all three dependencies, group it as bundle and then use this asset’s name as dependency for sec and thr. The error you are getting is to prevent publishing duplicated assets.

But these two AssetBundles have assets on their own.




class SecAsset extends AssetBundle

{

    public $sourcePath = '@assets/sec_asset';

    public $css = [

        'sec.css',

    ];

    public $js = [

        'sec.js',

    ];

    public $depends = [

        AppAsset::class,

        ActiveFormAsset::class,

        ValidationAsset::class,

    ];

}



And listing the dependencies only here is not working correctly. If I don’t add them to the assets command config file, they will be put into the general “all” target.

I created a working example on github.

Reproduce:




git clone git@github.com:hofrob/yii-asset-bundle-test.git

composer install

/init --env=Development --overwrite=y



for convenience there’s now a bash script “assets”

I use lessc and uglifyjs for compressing. edit frontend/config/assets.php to change

execute




./assets



and inspect the files in frontend/web/assets/js/

Now the dependencies listed in TwoAsset and ThreeAsset are in all-XYZ.js (search for "yii.validation")

and in two-XYZ.js and three-XYZ there’s only the console log message from the JS file directly attached to the AssetBundles.

This is just one mystery that I cannot solve :slight_smile:

To work around that, I listed the dependencies declared in TwoAsset and ThreeAsset in my asset command config

see the git branch “dependencies-in-asset-config” or in particular this change. This of course doesn’t work because of




Error: Target 'two' and 'three' cannot contain the bundle 'yii\widgets\ActiveFormAsset' at the same time.



So what am I missing. I’m still not sure if I found a bug here.

regards and thanks in advance!

hofrob

What I mean is to do this:




class SharedAsset extends AssetBundle

{

    public $depends = [

        AppAsset::class,

        ActiveFormAsset::class,

        ValidationAsset::class,

    ];

}


class SecAsset extends AssetBundle

{

    public $depends = [

        SharedAsset::class,

    ];

}


class ThrAsset extends AssetBundle

{

    public $depends = [

        SharedAsset::class,

    ];

}


return [

    ..

    'targets'       => [

        ..

        'shared' => [

            'depends'  => [

                SharedAsset::class,

            ],

        ],

        'sec' => [

            'depends'  => [

                SecAsset::class,

            ],

        ],

        // ...

    ],

];



I’m not sure if this what you want…

Ok, so 4 targets? "all", "shared", "sec" and "thr"? Yea, that could be possible. Thanks for your answers!

I will have to settle for something eventually. For the moment I will continue to try to reduce requests (one less target) on my site :D . I’ll probably have to dive into the depths of yii to find an answer ;)