More dynamic css and js discussion

Dec 12, 2009 at 6:28 AM

One more feature needed.

Defining groups like you have and then referencing those groups - that is fine, great, etc.

However, what is more realistic to me is this:

I will have a certain number of groups for sure.  I will want to use the groups exactly as you have them.

I will then have particular web pages that use additional scripts.  The scripts used may be another group or they may be individual scripts.

Ideally, all these would be combined into one final request.  The same holds true for css files.  May have specific css files in certain views, etc.

The way to handle this is to create additional helpers that do not directly output the script.  So at the top of the page in the site.master (MVC here) you would have

 

<%= Html.Combres.Scripts.OutputGroup("one").whatever() %>

 

In individual views, you may add scripts or add groups.....

Then at the bottom of the master webpage, you would have:

<%= Html.Combres.Scripts.Render() %>

That final render would take all the requests given to it from all views and construct the link to output the script/css link.  This would be the final piece necessary.   Optionally, what was proposed by burningice would be helpful in that regard .  Why create a resource group in your config for some view specific javascript file that is only used in one place.  The ability to reference combres.axd/js/somefile.js and have that minified/compressed with proper headers, etc.   We of course lose versioning with this - which is a KEY component you are providing and KEY to the caching.  This means these stand along .js and .css files would need to have the versions in the filename. 

I know I have posted a number of questions/suggestions/etc - but your product looks great and I hope you welcome these ideas/suggestions/questions.

 

 

Coordinator
Dec 13, 2009 at 3:17 PM

@waynebrantley:

Thanks a lot for your suggestion.

>>That final render would take all the requests given to it from all views and construct the link to output the script/css link.

There's a problem with this: let's say Page A and B both uses master page M.  Working this way means whatever scripts/CSS shared by A & B (referenced in M) would be requested separately by the browser - it's a waste of both CPU and bandwidth.  On the other hand, the current Combres' resource set structure would solve this problem (e.g. create 3 separate resource sets, 1 for M, 1 for A, and 1 for B - once M's set is downloaded by the browser, it's properly cached...).

>>what was proposed by burningice would be helpful in that regard

I'm not so sure about that though.  I think 1-resource resource set should do what is proposed here without losing all the benefit of versioning, minification switch, debugging setting etc.  And that you can reuse the link to that 1-resource resource set in as many places as you want.  Also, from the described usage of that post (including the 'inherit' feature), it sounds like it would result in the same same problem described in the above paragraph.

What do you think?  

 

 

Dec 14, 2009 at 5:33 PM

The pretend Combres object I used above would gather a list of what scripts were requested.
It could then dynamically create a unique group based on the scripts that were requested.  It would then write a script to request that group.
So, it would all still be combined and such.

The 'issues' I am having to request this above are:

1)  DRY - do not repeat yourself.  When in a master page/view/partial view scenario any number of scripts may be required.
In the current scenario, I would have to specify the groups like below and it gets ugly fast.

<scripts>
   <group name="default">
      <file path="~/jquery.1.4.js" />
      <file path="~/jquery.Validation.1.5.js" />
      <file path="~/file1.js" />
      <file path="~/colorbox.js" />
   </group>
   <group name="debate">
      <file path="~/jquery.1.4.js" />
      <file path="~/jquery.Validation.1.5.js" />
      <file path="~/file1.js" />
      <file path="~/colorbox.js" />
      <file path="~/debate.js" />
   </group>
   <group name="debateAdvanced">
      <file path="~/jquery.1.4.js" />
      <file path="~/jquery.Validation.1.5.js" />
      <file path="~/file1.js" />
      <file path="~/colorbox.js" />
      <file path="~/debate.js" />
      <file path="~/debateadv.js" />
   </group>
</scripts>

One user suggested a feature to make this situation better:

<scripts>
<group name="default">
<file path="~/jquery.1.4.js" />
<file path="~/jquery.Validation.1.5.js" />
<file path="~/file1.js" />
<file path="~/colorbox.js" />
</group>
<group name="debate" inherits="default">
<file path="~/debate.js" />
</group>
<group name="debateAdvanced" inherits="debate">
<file path="~/debateadv.js" />
</group>
</scripts>


2)  Using master pages, how can I decide what group to output?   In the master page, I would use the default group.  However in a particular view, I may want the "debateAdvanced" group.  I could specify the script group to be output in each page - requiring each view to include the script group it needs.  One way would be - content groups have 'defaults' - so I could output default and then any view with specific requirements could overwrite that group.  That can work.  However, what about partialviews in MVC?  These do not have the ability to update any 'content groups' - what if one of these partial views needs a script?  Any view could include multiple partial views - each needing their own specific scripts.  So, what would be nice is to have each view or partial view or user control ask for the file/group it needs - then when all views are finished rendering - something would output it.  

Thoughts?

 

 

 

 

Coordinator
Dec 15, 2009 at 2:59 PM

1.  I wouldn't do that myself.  Instead I would structure the groups as follows:

<scripts>
<group name="default">
<file path="~/jquery.1.4.js" />
<file path="~/jquery.Validation.1.5.js" />
<file path="~/file1.js" />
<file path="~/colorbox.js" />
</group>
<group name="debate">
<file path="~/debate.js" />
</group>
<group name="debateAdvanced">
<file path="~/debate.js" />
<file path="~/debateadv.js" />
</group>
</scripts>

Then in the page that needs both default & debate, I include both of them, i.e. 2 CombresLink()/CombresUrl() calls (resulting in 2 HTTP requests). Suppose the default set is shared by multiple pages (it should, otherwise there's no point creating a separate default set), then its resources do not need to be processed again per new page (that uses the default set).

Structuring the sets as suggested by you means the shared scripts are combined, minified, compressed, downloaded for each page using the set "inheriting" from the default set. 

Anyway, I think Combres should just provide option to those who need, so it should be good to implementing the inheritance feature.  I've added a tracking ticket here for this: http://combres.codeplex.com/WorkItem/View.aspx?WorkItemId=5605.

2.  If you structure the resource sets as I mentioned in #1, then each view/partial view can control which set it includes.  Granted, that will result in many HTTP requests.  (As mentioned above, this can sometimes be expected if some sets are shared by multiple pages).  But yes, I agree that if there's an option to combine everything in a page then it's better.  I've added a tracking ticket here for this: http://combres.codeplex.com/WorkItem/View.aspx?WorkItemId=5606.