Assetbundle Position On Page


(Arman) #1

While working on new project with Yii2, I’ve decided to use new AssetBundle to leverage it’s compressing and converting functionality later on. It’s great addition to Yii. The concept of asset bundles on it’s own is great even without compressing and converting, but…

Unfortunately I’ve noticed that there is no any way to define where the asset bundle should be inserted on page. View::registerJs has second argument, where you can define position on page. AssetBundle class uses the same function to register all js assets with default/empty argument (meaning that assets are inserted in head section). But jQuery for example can (usually must) be loaded in right before closing body tag. And it is good practice to load jQuery and other heavy libraries there, so that the page is loaded faster (content of the page).

Won’t it be reasonable to add an option to asset bundle class to define where to load js scripts?

Do I need to open issue or even apply patch for it?

(I just wanted to listen for an opinion of other devs)


(Alexander Makarov) #2

Default isn’t head. It’s end of body.

Also you can’t specify position manually since that will override dependencies.


(Kvisweswaran) #3

Yes I think its for dependency management. If you can ensure dependencies are ok … you could still achieve what you want to some extent by using multiple bundles and split your js files between the bundles.

You can control the jsOptions in the bundle, to control the positioning of the js files for the bundle. I have not tested this, but this should theoretically work. For example:




class MyBeginBundle extends AssetBundle {

    public function init() {

        $this->jsOptions['position'] = View::POS_BEGIN;

        parent::init();

    }

}


class MyEndBundle extends AssetBundle {

    public function init() {

        $this->jsOptions['position'] = View::POS_END;

        parent::init();

    }

}



In your view or your layout file:




MyBeginBundle::register();

MyEndBundle::register();




(Qiang Xue) #4

Yes, you should use “jsOptions” to control the insertion position of the js files in your bundle. The options will be applied to ALL js files in the same bundle. This is so because the potion itself indicates some dependency and we don’t want it to mess up with the bundle dependency.


(Arman) #5

@samdark thanks.

Sorry, I’ve just noticed that they are in the end of body.

@Kartik, @Qiang thanks for your answers. OK, now I see how I can do that. It’s great thanks.

I simply was looking on registerJs function in View and thought that the same function was used in AssetBundle internally. But it turned out that AssetBundle uses registerJsFile and position is the 3rd argument, not 2nd as in registerJs.


(Naito Neko) #6

I tried to do this, it seems that it was what I was looking for. But I am having the following errror :

“Class ‘app\assets\View’ not found” and the error is when I do this -> “$this->jsOptions[‘position’] = View::POS_END;”

I understand that now “$this” refers to the view, but how I can access the local parameter then ? ( I tried using $jsOptions[‘position’] without luck neither ).


(Kvisweswaran) #7

Remember that namespaces are very important in Yii 2.0. You must include this in the beginning of your code for the [font="Courier New"]View[/font] class to be identified:




use yii\web\View;




(Naito Neko) #8

Thanks ! I am still trying to get use to namespaces. :).


(Phuc Nghiemtuc) #9

Very nice, its work for me!

Thank you


(Ifrops) #10

Good day!

As I understand it, the $JsOption[‘position’] used for all files JS.

What should I do if I want to use a different JS for different positions.

For example, I have js_for_head.js and js_for_end.js.

First file I want to place in the head, and the second at the end.

Thank you.


(H) #11

Dragging this old thread up as there are very few mentions that this has since changed. Even the documentation doesn’t mention it or show an example, but the ability to add options at the file level is now available in asset bundles.

For example:


['path/to/js-file.js', 'position' => \yii\web\View::POS_HEAD]

Hopefully that’s useful to people, including future me.