`forceCopy` per Asset Bundle

  1. Problem
  2. Solution
  3. Links

Note: The following document describes a possible workaround, if you have issues with asset publishing. For many people this will just work fine.

Problem

During development and depending on your setup you may need to use the options forceCopy or linkAssets of the asset manager to work around possible file-system and permission issues.

While the former tends to become very slow with a large number of assets, the latter may not be convenient, since it does not use any callbacks during publishing (eg. for limiting published files) or the symlinks point to a non-existent location, when using your project within a virtual machine.

Solution

But you can tell Yii to forceCopy a specific asset bundle during development, eg. your main application AssetBundle, which is generated with a LESS or SASS compiler.

class AppAsset extends AssetBundle
{

    [...]

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

        // /!\ CSS/LESS development only setting /!\
        // Touch the asset folder with the highest mtime of all contained files
        // This will create a new folder in web/assets for every change and request 
        // made to the app assets.
        if (YII_ENV_DEV) {
            $files  = FileHelper::findFiles(\Yii::getAlias($this->sourcePath));
            $mtimes = [];
            foreach ($files AS $file) {
                $mtimes[] = filemtime($file);
            }
            touch(\Yii::getAlias($this->sourcePath), max($mtimes));
        }

    }
}

In the example above, during the init-stage of the asset bundle, we touch the source folder to trigger Yii's publishing process, which checks if the source folder has a modified mtime.

The way of doing this could be greatly improved (eg. with behaviors, DI, ...) and SHOULD NOT be the default setting in an extension, since it makes very hard to adjust the settings in the 3rd party code.

Links

Related information