16 Mar 2010 8:29 AM #1
I searched the forums and read all of the tutorials and app-design & architecture guides i could find. and i couldn't find any good practiced of deferring the initialization of child components.
for example, if placing several "xtype-defined" components into card region with deferredrender=true in it's layoutconfig, and placing alerts inside all component's "initComponent" method, all alerts are fired. that means all the hierarchy components get created.
any tips how to NOT create the childs untill they needed ( except of ugly hacks with "addItem" & "doLayout" inside "afterrender" event ) ?
thanks in advance.
16 Mar 2010 10:22 AM #2
17 Mar 2010 2:44 AM #3
stever - i saw that one, and i like the direction. indeed it finally does what i meant, but i don't like the hacky way. however it will definetely help me. tnx.
let me sharpen my thoughts. and please don't threat it like "Please write me code plzzz". I'm ready do do some dirty job myself and share it of course. but i need your help guys.
1. the deferredInit should not require any hacks to each component it will apply to. this way it will be a "plug-and-play" setting. probably achieved by overriding component / componentManager classes.
2. deferredInit will apply to only xtype-defined components ( component configurations ), and create them only when the components are needed ( activated/used). ofcourse with all the stuff like applying container's defaults , firing event when initialized etc etc.
3. optionality to load code on-fly ( 'deferredInitSource' config / xtype<>sourcefile mapping ? ), so the code needed to create the deferred component would not be even loaded before it's needed.
4. will work on extjs3. older versions support is nice but not crytical.
5. other suggestions are welcome.
I think such functionality ( In the right hands.. ) will really boost performance , decrease loads , and dramatically decrease initial loading time of large apps.
Passing the ball back
17 Mar 2010 7:13 AM #4
Perhaps you should flesh-out your thoughts still further.
Is it valid to say that what you might be describing here is a sort of "proxy" or "wrapper" that one could put around some other, "stock" component? In other words:
(1) The components inside of this 'wrapper' won't be instantiated until someone actually touches it. Until then, they are simply "xtype"-based config hashes.
(2) Then, the wrapper will initialize the components and instantiate them within the same container that now contains the wrapper.
(4) Once the wrapper "goes off," it becomes empty and dormant.
I am not sure of the details of this idea that just popped into my head, but I like it a lot ... Instead of hacking the behavior of each component, we build "one hack to instantiate them all."
Tossing the ball back ...
17 Mar 2010 8:04 AM #5
I initially tried the wrapper idea, but it was far too much work. The subtle bugs were endless (things like 'ref', etc.).
My work did not require rewriting each component, but the pseudo code was specific to tabpanel so it would be easy to understand. Some things like menu will need to override default behavior, like it already does.
Using xtypes is the preferred method of course (why create a component that you way not use up front?). But by changing the items list, it is still up to the user.
In my opinion, loading resources on the fly doesn't make things faster on a component by component basis. Though component bundles work great. I think that is why when you build from svn you get more than just ext-all, but around seven files that you can load at will. Ext should have a better handle on loading. YUI, Dojo, etc., all have had this for a while now.
Lastly, I know the scheme works. I have it running and the performance increase is quite incredible for many situations.
17 Mar 2010 8:11 AM #6
wrapper : Indeed it's the main problem. but i think it's possible.
do you still have your tries code ? maybe we can overcome the bugs together ?
deferred resource loading : it may make a really big difference when facing hundreds of files - especially on older browsers. take in account that if component A (and only it) uses components [B,C,D,E,F,G], then not -loading file of component A means not loading 7 files, and it cascades further. smart serverside implementation can merge the required files into one, minify it and cache for further similar-requests.
one more thing which will be theoretically possible with this approach is not using the ext-all at all - by defining somewhere the relations, it's theoretically possible to load only the extjs component files needed, joined , minified and cached by server , on-fly .
if it wasn't a problem to load endless code , so why ext-team giving and recommending to build "custom builds" ?
I'll try to make some proof-of-concept and post here and on some host ( google ? ). any tips are still very appreciated.
Also, i'm very interested to hear from the gurus about that, before reinventing the wheel or making something stupid
18 Mar 2010 8:42 AM #7
My intuition is that a "wrapper" approach is probably the only one that realistically could work. And yes, it would have its trade-offs: you obviously cannot have a "ref" to something that does not actually exist yet. But that really is a trade-off that is created by "the thing that you are doing, in principle," vs. a problem with any implementation. Code simply cannot refer-to anything that does not yet exist. (Furthermore, it can't realistically "demand load" it because the loading and object-instantiation process is asynchronous.)
(Why do I hear a voice from my past whispering ... "holy overlays, batman!")
If you tried to shove this functionality like a cherry-stake through the heart of ExtJS, you would probably kill it. That's because, if this were intended to be "a fundamental and universally-available design feature," you'd basically have to start-all-over with the architecture of the entire thing. And that ain't gonna happen. But a "lazy loader" object could be created, and successfully implemented and deployed as long as you remained very mindful of the compromises.
It would not be exactly like "xtype," though, because that feature does rely upon a stable of object-instances which hang off of the xtype-hash within the system. In this case you might well wish to initially have just "stubs" hanging there ... another form of "lazy loader" that would know how to fetch and instantiate the "real" object (replacing itself in the process).
All things considered, what you would come up with is a very-different form of application, "different" to the extent that you chose to use lazy-loading.
18 Mar 2010 8:59 AM #8
Well, since I have done it the other way already, I know the deferredCreate works. And my patch fixes the issues with form elements in hidden deferredRender containers as well (though, why bother?). So I know that the "wrapper" way is most certainly not the only way that could work.
I'd like to know some of the implementation details on your wrapper method. The back references to it are uncontrollable as I found out when I tried it (the container's mixedcollection, not withstanding).
BTW: if your always used deferredCreate instead of deferredRender, you wouldn't have to worry about checking for this.rendered all the time when doing something. In fact, you would avoid some bugs like the Slider currently has since it does not always do this check.
18 Mar 2010 9:12 AM #9
i actually thought of another way:
there will be a 'ghost' component extension ( xtype='ghost' ). it will have property 'ghostOf', indicating the xtype needed.
this component will override it's superclass ( Ext.Component ), in order to :
1 load required script(s)
2 instantiate the required class ( using its own initialConfig )
3.replace himself with the actual component ( inside its container )
4.make references (ref) and other required relations
5.render the new component
6. do-layout of it's container
7. notify about whatever needed
8. remove himself entirely
9. etc etc.
it will do it the moment it's requested to be shown or expanded or activated or specifically requested to be created ( doCreate method ).
usage will be sort-of:
it even can be: ... new ext.ux.Ghost(...).... , and the ghost class will be able to find references to himself inside container and redirect them too .
that way it will be non-intrusive for extJs architecture ( for example, may have region config for the border layout ).
18 Mar 2010 9:26 AM #10
Tried that. The back-references are all unknown except for the container's mixedCollection, which leads to lots of subtle bugs to track down. I tried both the letter/envelope and the in-place replacement methods. Both were far more work.