Yii2 AssetBundle publishOptions pattern syntax? - yii2

Might be stupid, but just wanted to ask if the syntax I'm using is correct when publishing asset's files. The Guide instructs to use folder names without trailing asterisk, however for me it does not work that way.
The weird thing is even if I specify to only publish css and images folder, the assetManager also publishes other folders in $sourcePath (luckily without files inside). What's more, when new files are added to images folder, they remain unpublished until I delete #web/assets folder. Is this to be expected?
<?php
namespace app\views\layouts\main\assets;
use yii\web\AssetBundle;
class ThemeAsset extends AssetBundle
{
public $sourcePath = '#theme';
public $baseUrl = '#web';
public $css = [
'css/site.css',
];
public $publishOptions = [
"only" => [
"css/*",
"images/*",
],
"forceCopy" => false,
];
}

The first note that you should set $sourcePath or $baseUrl not both of them (If you set the both, the former overwrites the last when assetManager calls publish method).
The weird thing is even if I specify to only publish css and images
folder, the assetManager also publishes other folders in $sourcePath
(luckily without files inside).
If you wanna avoid asset manager to publish this folders, you must mention them on except parameter of publisOptions:
'except' => [
"doc/",
"img/",
],
What's more, when new files are added to images folder, they remain
unpublished until I delete #web/assets folder. Is this to be expected?
Yes! It's a natural behavior. You may set forceCopy property of publishOptions to true in development mode. This causes to update asset contents in each refresh. Easily you can use Yii production constant: YII_DEBUG.
public $publishOptions = [
'only' => [
'js/',
'css/',
],
'forceCopy' => YII_DEBUG,
];
So totally you have an asset manager like this:
<?php
namespace app\views\layouts\main\assets;
use yii\web\AssetBundle;
class ThemeAsset extends AssetBundle
{
public $sourcePath = '#theme';
public $css = [
'css/site.css',
];
public $publishOptions = [
"only" => [
"css/*",
"images/*",
],
'except' => [
"doc/",
"img/",
],
"forceCopy" => YII_DEBUG,
];
}

Related

How to include npm-asset packages inside yii2 project?

I have successfully installed npm-asset/socket.io package and its dependencies by using Asset Packagist in yii2. Now, I cannot include it in my pages. I tried in AppAsset.php like this:
public $js = ['#npm/socket.io/client-dist/socket.io.js'];
it did not work:
GET http://project.localhost/#npm/socket.io/client-dist/socket.io.js
net::ERR_ABORTED 404 (Not Found)
Then, I tried to include that file inside view file like this:
<script src="<?php echo Yii::getAlias('#npm').'/socket.io/client-dist/socket.io.js' ?>"></script>
it gave me this error :
Not allowed to load local resource:
file:///C:/Projects_folder/Php/Yii2/project/vendor/npm-asset/socket.io/client-dist/socket.io.js
I need help with how to use this js file inside view files.
The sources installed by composer are placed in vendor folder which is not directly accessible. You need to publish the assets and then include the published resources.
To do that you can make an asset bundle for socket.io for example like this
namespace app\assets;
use yii\web\AssetBundle;
class SocketIOAsset extends AssetBundle
{
//this is path where source files that needs publishing are located
public $sourcePath = "#npm/socket.io/client-dist";
public $css = [
];
public $js = [
'socket.io.js'
];
}
Then in your AppAsset bundle add the SocketIoAsset into $depends property
class AppAsset extends AssetBundle
{
public $basePath = '#webroot';
public $baseUrl = '#web';
public $depends = [
SocketIOAsset::class,
// ... other dependencies ...
];
// ... other definitions ...
}
Now because your AppAsset depends on SocketIOAsset, the folder defined in SocketIOAsset::$sourcePath will be published when AppAsset is registered, and files in SocketIOAsset::$js array will be linked.

appendTimestamp and registerAssetBundle

I am using the following configurations to add the timestamp in the assets path via asset manager.
'assetManager' => [
'appendTimestamp' => true,
appAsset.php
class AppAsset extends AssetBundle
{
public $basePath = '#webroot';
public $baseUrl = '#web';
public $css = [
'/css/style.css'
];
}
In view
AppAsset::register($this);
But in html I still see '/css/style.css' without timestamp.
I saw solution
https://github.com/yiisoft/yii2/issues/9101#issuecomment-267274327
$file = '/css/style.css';
$asset = new \yii\web\AssetBundle(
[
'js' => [ltrim($file, '/')],
'basePath' => '#webroot',
'baseUrl' => '/'
]
);
$this->getAssetManager()->bundles[$file] = $asset;
$this->registerAssetBundle($file);
This example is work. '/css/style.css?v=12557565'
Is there any method write registerAssetBundle() not in a view files?
First of all, what is public $sourcePath = '#frontend/assets';? it is not the correct path this path actually has your Asset.php files, not the source files. According to the documentation
sourcePath: specifies the root directory that contains the asset
files in this bundle. This property should be set if the root
directory is not Web accessible. Otherwise, you should set the
basePath property and baseUrl, instead. Path aliases can be used here.
Just place your .css files under frontend/web/css and .js under frontend/web/js and remove the sourcePath you do not need it as looking at your code, only in case if you had your source files under frontend/themes/basic then you would use sourcePath like public $sourcePath = '#frontend/themes/basic/'; because this path isnt under the web accessable directory
And for adding the timestamp You do not have to do anything other than adding the appendTimestamp options under the components section in the assetManager, make sure you are adding assetManager under components. and it will automatically start adding ?v=125453612 with all CSS and js files
your AppAsset.php
class AppAsset extends AssetBundle
{
public $basePath = '#webroot';
public $baseUrl = '#web';
public $css = [
'css/style.css'
];
}
frontend/config/main.php
'components' => [
..........
..........
'assetManager' => [
'appendTimestamp' => true
]
..........
..........
],
and your file will start looking like this
I can show you a live example of the same site if you want to have a look into the view-source
EDIT
As you provided the source code screen grab and looking at your code I can tell that you are using trailing slash / with your files, remove the trailing slashes from your source files path, I also overlooked it the first glance but then looking the code i couldn't find any other thing than this one that could be wrong. they should be like this
'css/new.css',
'css/new2.css',
and same for the js files too.
Try write public $css and public $js without forst slash ("js/.." instead "/js/..").

Yii2 location from dependencies in custom asset

I have a path something like /actions/users/someaction in the frontend and I want to use the Bootstrap-Asset (located in /backend/web/assets/xxxxxx/) from the backend.
So I created an asset called "ActionAsset" with following content:
class ActionAsset extends AssetBundle
{
public $basePath = '#backend';
public $baseUrl = '#web/backend';
public $css = [
'css/external.css',
'css/overwrite-bootstrap.css',
];
public $js = [
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BackendBootstrapAsset',
];
}
The included css are just working fine, but the dependencies are always saved in /frontend/web/assets/.
My question is (and I really searched for weeks) how to change this location to /backend/web/assets.
You need to define $sourcePath. Yii2 AssetManager will copy (or symlink) your assets in your current web/assets/ folder.
From the docs
sourcePath: specifies the root directory that contains the asset files in this bundle. This property should be set if the root directory is not Web accessible. Otherwise, you should set the basePath property and baseUrl, instead. Path aliases can be used here.
So change your code to:
class ActionAsset extends AssetBundle
{
public $sourcePath = '<path to your asste content>';
public $css = [
'css/external.css',
'css/overwrite-bootstrap.css',
];
public $js = [
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BackendBootstrapAsset',
];
}
Or: Just overwrite your asstetbundle in #frontend/asset and set $sourcePath property accordingly:
class FrontendActionAsset extends ActionAsset
{
public $sourcePath = '<path to your asste content>'; //you don't need more
}
Asset Publishing
As aforementioned, if an asset bundle is located in a directory that is not Web accessible, its assets will be copied to a Web directory when the bundle is being registered with a view. This process is called asset publishing, and is done automatically by the asset manager.
By default, assets are published to the directory #webroot/assets which corresponds to the URL #web/assets. You may customize this location by configuring the basePath and baseUrl properties.
Instead of publishing assets by file copying, you may consider using symbolic links, if your OS and Web server allow. This feature can be enabled by setting linkAssets to be true.
return [
// ...
'components' => [
'assetManager' => [
'linkAssets' => true,
],
],
];
With the above configuration, the asset manager will create a symbolic link to the source path of an asset bundle when it is being published. This is faster than file copying and can also ensure that the published assets are always up-to-date.
https://www.yiiframework.com/doc/guide/2.0/en/structure-assets

How to access css/js file for layout of a module in Yii2

I have a module named social with the directories like this :
frontend
-- modules
-- social
-- assets
-- SocialAsset.php
-- controllers
-- views
-- default
-- layouts
-- main.php
-- web
-- css
-- js
-- img
Module.php
I want my module have an own layout. Because of that, i add file SocialAsset, main.php for layout, css, js and img. But, unfortunatelly i can't access my css/js/img files.
SocialAsset file :
<?php
namespace frontend\modules\social\assets;
use yii\web\AssetBundle;
class SocialAsset extends AssetBundle
{
public $basePath = '#webroot';
public $baseUrl = '#web';
public $sourcePath = '#app/modules/social/web';
public $css = [
'css/social.css',
'css/toolkit.css'
];
public $js = [
'js/jquery.min.js',
'js/social.js',
'js/toolkit.js',
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
];
}
in main.php i use the SocialAssetfiles like this :
use frontend\modules\social\assets\SocialAsset;
SocialAsset::register($this);
Could someone to help me to solve this problem ?
You should only set sourcePath in your asset bundle :
sourcePath specifies the root directory that contains the asset
files in this bundle. This property should be set if the root
directory is not Web accessible. Otherwise, you should set the
basePath property and baseUrl, instead.
This means you should simply remove $basePath and $baseUrl in your assset bundle, Yii will then publish your files.
Read more : http://www.yiiframework.com/doc-2.0/guide-structure-assets.html

Yii2 How to enable default assets only in certain modules

I am using basic yii2 app, I have disabled the boostrap css and js in web.php config but i want to enable it inside the module called admin.
I tried adding like this, for component section in config.php under admin module folder, but no luck!
'assetManager' => [
'bundles' => [
'yii\bootstrap\BootstrapPluginAsset' => [
'js'=> ['js/boostrap.js']
],
'yii\bootstrap\BootstrapAsset' => [
'css' => ['css/boostrap.min.css']
]
],
],
How can i achieve this?
In your module's init() method, you can override an exist asset bundle like below:
public function init() {
\Yii::$app->assetManager->bundles['yii\bootstrap\BootstrapAsset'] = [
'css' => ['css/bootstrap_NEW.css']
];
parent::init();
}
In above example, we override yii\bootstrap\BootstrapAsset CSS file in our module. So, in this module, it uses bootstrap_NEW.css instead of its default.
Please note that, you can do this in application globally, not specially in module's init() method. It was just a suggestion to solve this specific case.
You should use asset bundles to handle this, no need to modify assetManager.
To disable Bootstrap, simply remove it from $depends in AppAsset :
public $depends = [
'yii\web\YiiAsset',
];
Create a ModuleAsset class in your module :
class ModuleAsset extends \yii\web\AssetBundle
{
public $depends = [
'yii\bootstrap\BootstrapAsset',
];
}
Make sure to register it in your module's views (you could use a custom layout) :
ModuleAsset::register($this);
Read more : http://www.yiiframework.com/doc-2.0/guide-structure-assets.html