Yii generated script and renderPartial

Qiang, thanks for your feedback.

Indeed, my proposal is quite as you described it :).

  1. Yes, that's possible.

  2. Correct. The load call also contains the literal function that would init any widgets contained in the AJAX response.

  3. That would be the case.

It's important to note, that each loaded js core file needs the call to register() in the end. The init code for widgets would stay as it is now, but get "encapsuled" inside a yii.load() call. There are 2 drawbacks i see with this:

  1. All js core scripts that are loaded by the loader need this register() call at the end.

  2. This means: We always need the loader present, even, if we don't use the loader for a page. Otherwhise we would get an error about missing jquery.yii.register().

Not sure, if this is acceptable. A workaround would be:

We add a "dummy" script with some bytes to every page that doesn't use the loader which contains an empty jquery.yii.register() method.

Then we need a way to differ between a loader and a non-loader page. This would require an additional parameter for render()/renderPartial() i think.

More feedback welcome :)

Quote

You probably would not want to load all scripts into a single file, besides the fact you need to know what all will mean for the whole app, it could mean that you bloat your single file too much.

Roundtrip between client and server to load additional even tiny js file could be more than the overhead of loading whole gzipped minified js while at once which contains all functions even not needed for this particular page. At the same time you are introducing code complexity and some additional assumptions. You won't gain much speed (maybe even opposite) because of network roundtrip latency but you will lose code clarity.

That's not necessarily the case. You could also load a gzipped minified file with the loader, if you want to. You just tell the loader what "core" scripts your minified js file provides and everything's fine.

Think more of it like an AJAX response tells the loader "hey, i need jquery.yiitab". The loader would check, if any of the already loaded scripts provides yiitab and loads it, if necessary.

Quote

That's not necessarily the case. You could also load a gzipped minified file with the loader, if you want to. You just tell the loader what "core" scripts your minified js file provides and everything's fine.

You didn’t get my point. The issue is that you can’t remove network roundtrip, independent of the size of the script to load. This roundtrip, not the script size, will provide the most negative speed impact. You need to minimize roundtrips, and one way to do that is to load all scripts in advance in a single file. Even if you load more scripts than you need, it will be faster than loading less scripts as a separate files.

Quote

Quote

That's not necessarily the case. You could also load a gzipped minified file with the loader, if you want to. You just tell the loader what "core" scripts your minified js file provides and everything's fine.

You didn’t get my point. The issue is that you can’t remove network roundtrip, independent of the size of the script to load. This roundtrip, not the script size, will provide the most negative speed impact. You need to minimize roundtrips, and one way to do that is to load all scripts in advance in a single file. Even if you load more scripts than you need, it will be faster than loading less scripts as a separate files.

I agree with this viewpoint, additional http requests does have significant impact on the overall perceived user experience. A goal that I often pursue is to only have 1 external js file and 1 external css file. Additional js and css on a per functionality basis are rendered inline within the page.

I see. So the alternative for the problem would be, that we include all js files (or a packed version of them) for all widgets that might get used in any AJAX HTML response for a page.

I guess this will not be a problem for "simple" widget js. When thinking about the loader i had more complex AJAX applications in mind with many >100K js modules. But in cases like that, YUI Loader could still be used separately, so also no problem.

Any chance that one of the solutions will make it in 1.0.2?

I'm afraid not. We won't rush to put in new methods in the framework until we are fairly confident and the code is relatively stable.

I changed some protected methods in CClientScript to public. That could be a workaround to solve your problem.

Another idea. How about adding adding a method registerAjaxView() to CController? In it’s render method it renderPartials all registered views without storing the output. The Ajax components in these views will register their necessary core scripts in the ClientscriptManager. That way we can do something like this in the action for the initial page:

<?php


public function actionIndex()


{


    $this->registerAjaxView(array('show','update'));


    ...


}

That would ease the process of deciding which clientscripts to include, as views are more handy to identify. This could also be used to find out, which js files to include in a packaged version for production mode.

I forgot the missing view data when calling renderPartial. So this approach is problematic.

Okay thanks qiang, that will make rudimentary functionality possible.

For the loader: Might it be possible that the load() request can check if functionality is already loaded (without the register() part), and if not just send a request to a php 'js-controller' which in turn sends the required js back? (minified and gzipped if desired)

Still a wise thing to do is wei's approach: determine the most used scripts and combine them into one.

Although renderBodyEnd() is now public, the generated JS gave problems still. This was caused by the jQuery replaceWith(), that will remove the referred element from DOM, so a next submit was not working anymore.

Replacing it with html() (and moving the script inside the DIV and not using the renderBodyEnd()) did the trick.