I'd like to have some of the ScriptManager features in the new Asp.net MVC model:
1- Script combining
2- Resolving different paths for external Javascript files
3- Minify and Gzip Compression
Here is what I found, but I'm not sure is the best way for MVC approach. In general what is a good approach to deal with Javascript code in the MVC model?
Maybe you could just create a new 'Scripts' controller with different actions serving different combinations of compressed JS files. Since MVC is designed with a resource oriented approach, i.e. URLs are now at the center of your programming model, why not define simple URIs for your Javascripts too ?
In your views, for example you could reference your files like this :
<script src="http://your_domain/scripts/all"/>
This would call your 'all' action, resulting in all your compressed script files being sent.
Of course you would need to code the combining and compressing for now, or maybe reuse the Scriptmanager internally, I don't know if it's possible.
This is just an idea though, currently I'm referencing individual javascript files directly in my master pages.
Try this:
http://www.codeplex.com/MvcScriptManager
MvcScriptManager is aimed to port certain key features available in AjaxControlToolkit's ToolkitScriptManager into the current ASP.NET MVC Framework. You will be able to use it as a control in your ASP.NET MVC application.
Features
Script combination (or concatenation). Scripts declared with MvcScriptManager will be combined on the fly into a single script file request when the page is rendered.
Script minification (or crunching) in release mode. Minification process is done only once at the first request that references the specific script. Subsequent requests will use the crunched script content in cache (see #5 for detail). Crunching can be enabled/disabled for each script.
Render localized resources for stand-alone script files. Localized strings will be appended to the script if specified.
Support configurable HTTP compression and expiration setting when outputing scripts.
Script caching with file dependency. Script file content is cached so that rendering combined script file will be much more performant. Cache dependency is linked to the physical file therefore any script update in the file system will be reflected in the cache instantly.
Support rendering scripts in debug/release mode based on the running environment.
Resolving different paths for stand-alone script files.
Support multiple MvcScriptManagers on a single page (or master page). Support both Master and Slave rendering mode so that scripts declared with one ScriptManager can be rolled over to another one for rendering.
Support web farm scenario...
Or how about including the ScriptManager itself, as the sole inhabitant of a solitary, once-per-page <form runat="server"> ?
Like this:-
<form runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnableScriptGlobalization="true">
</asp:ScriptManager>
</form>
Works for me.
P.S. You'll need to ensure that this form tag never gets embedded within another form. Nested forms don't work.
Found this researching much the same problem: A Simple ScriptManager for ASP.NET MVC - written after this question was answered so added for reference.
In the first instance I'm going with the brute force solution i.e. stick it all in the master page (especially as one can now pull jQuery from Microsoft's CDN) - then we're going to investigate options for more optimal solutions.
MVC 4 now includes Bundling and Minification helpers. You define all of the scripts that go into your bundle, and MVC will take care of bundling, compression, cache busting, etc.
http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
Related
Just wondering if it's possible really. I have a large website, with hundreds of JS and HTML files.
Is it possible to compile these down into a single DLL, so when deployed to customers web servers they don't see or have access to the code?
I have never tried, but theoretically it is possible to achieve that.
HTML - compile (I assume you use *.cshtml)
Set <MvcBuildViews>true</MvcBuildViews> in the <PropertyGroup> element of your .csproj file.
JS, you will have to ember js files as resources, use ScriptManager to load it
CSS - hack it, with same methods as js, but using Add CSS File in DLL (Class Library)
Even if you minify, obfuscate, compile and ship it as dll, I will be able to see html/css/js with developer tools. And honestly none of it make sense, horrible debugging, no caching.
you actually can,
ember your js and css files (view remigijus answer).
When you publish,
in the configure part of the settings tab (see capture below), be sure to uncheck
"allow precompiled site to be updatable" <--- will compile the cshtml
"chose merge page and control in a single assembly"
but i raise the same warnings than your other answers, it's useless and counterproductive. Keep in mind that anyone can decompile a .net assembly anyway
I am working on project with larger javascript files.I can add these javascripts in one of the two ways.
1) create a separate class library project and have the javascript files there as embedded resource.Include a reference of the dll into the web project and then include those using scriptmanager as webresource.
2)Have these files in a separate folder and then simply add these files using the script tag and there path.
I am not going to paste the javascripts in my page within the script tag cause they would mess my pages mark up.
So I would like to know which one is better of the above 2 ways.In either of the 2 ways everytime i load the web page i see GET request for the js files.If i create a javascript dll will the browser cache it?
You can't create "javaScript dll". JavaScript is a client-side stuff, dll is server-side. No matter in which project your javaScripts are, it will still be sent to the client and executed there. So it makes no sense to put JS files to another project (especially as resources)
We usually want to minify and bundle the JS files, so the client will do less requests to the server and also to reduce the amount of data to transfer.
For minifying the JS files I would recommend to use Web Essentials extension to VS. It is very handy and can make web programming easier.
Minification will remove all unnecessary characters from the JS file and it will also reduce the length of the identifiers (like method names and variable names).
You can learn about bundling here. It is useful when there are more JS files to load to load all of them at once.
I am working on an enterprise application development in ASP.NET MVC3. Of-course I have different master layouts and multiple views.
My concerns
Including all js/css files in master layout might affect the performance of the page
Including the files in views (where it is required) are creating duplicate references (kick-off jquery/other libraries)
More the references, the more the back&forth requests between client and server - which in turn affect the performance of the output page
My Thoughts
Create a custom list of required resources and store it in ViewBag. Let the master layout refer this object to include the js/css files
Or add the link referring an action with some key (an unique value to identify the page being rendered) and dynamically generate an output with all required resources as a single response. And cache the output (inmem/staticfile) with the unique key for succeeding requests. A kind of custom resource bundling.
Please share your ideas, any thoughts and suggestions are welcome!
EDIT: Sep.17.2012
Below answers are more talking about optimization techniques in web application development world - appreciating those answers.
I would like to discuss from an architectural perspective, focusing on creating a dynamic resource collection required by the page being rendered.
For example, in specific views I would like to use jQuery UI which requires jquery-ui-1.8.11.min.js, and in certain views I would like to use MVC3 ajax which requires MicrosoftMvcAjax.js and jquery.unobtrusive-ajax.min.js
I don't want to include permanent reference in master layout, which will result in loading these js for all views. Rather I would like to include the js files dynamic during runtime.
Hope this might have added clarity!
Thanks for the help - Vinod
You need to think about reducing your download size first:
putting all your js and css into as few files as possible. This is because a client can only open 2 HTTP channels (most browsers now support more, info here) at any one time, all file downloads after this are queued until the previous ones finish downloading.
minify your js and css.
Once you've got this down to a reasonable size then you can think about the above. You want to download, the smallest amount of content upfront, so in the master. This will improve performance because then the client can cache it. Caching is a good thing, this stops the client having to request the js and css every time they visit a page on your site.
You might also want to think about applying HTTP expiry headers.
Yahoo do a good site on lots of these ideas: http://developer.yahoo.com/performance/rules.html
Also don't put your js in the viewbag. This is unnecessary overhead and load on the server. Just add a reference in your pages!
MVC4 now supports bundling
I'm pretty new to MVC and I can't decide on the best way to store cshtml files and their respective javascript code. Some JS code in my project needs to run globally, but most of it is entirely tied to specic views or partial views.
If I put the javascript in the views, I get a mess of inline uncacheable javascript, if I put it in one central file, I lose modularity.
I heard that in MVC4 there are going to be minification features, is there something I can do with MVC3 that will allow me to choose in the Views which javascripts to include and then group them and minify them automatically? (maybe even in groups?)
Cassette it's essentially the same thing as the upcoming MVC4 bundles.
In your view page, you can reference scripts and stylesheets using Cassette's Bundles helper class.
#{
Bundles.Reference("Scripts/jquery.js");
Bundles.Reference("Scripts/page.js");
Bundles.Reference("Styles/page.css");
}
<!DOCTYPE html>
<html>
...
In addition, Cassette has native support for Less and CoffeScript. It has also support for HTML Templates, if you are interested in client side MVC frameworks like Knockout.js or Backbone.js.
Still you have to choose how to group your content. As the official documentation is suggesting, probably the best choice is to treat bundles as units of deployment.
Keep in mind that a bundle is a unit of deployment. If any asset in a bundle changes, then the entire bundle has to be downloaded again by web browsers. So perhaps group shared code into a bundle and put page scripts into their own bundles.
You can put the javascript in separate files, for each view. Then in the _Layout.cshtml enter a #RenderSectionto the head:
<head>
<script src="#Url.Content("~/Scripts/jquery-1.7.1.js")" type="text/javascript"></script>
#RenderSection("head",false)
</head>
Then in each view, you can put a section that will be rendered into the header:
#section head{
<script src="#Url.Content("~/ViewScripts/Order/New.js")" type="text/javascript"></script>
}
You'll want to use a method like this:
http://www.viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution/
See this post:
Using Rails 3.1, where do you put your "page specific" javascript code?
It is not a best practice to use script in partials (in my point of view)
is suggest you to write partial specific script to separate js and bind events on page load or if partial was loaded via ajax then on success event.
then you can be sure that events are not bound multiple times and view is just a view
#Anders approach is good if you require the scripts to be in the head tag. But I find that most times it is not required if it is page specific JavaScript. You can put your script tags that reference your script files wherever they are required in the View. Automatically bundling and minification will be supported in ASP.NET 4.5. Until that time you can integrate yuicompressor into Visual Studio.
I wanted to get your opinion about managing scripts in ASP .NET MVC. There are 2 problems I am particularly curious about:
Tracking script include dependencies of views
Managing and minifying view scripts
Just like in many projects my views are composed of several partial views and editor templates. I like to keep the scripting relating to these views in the same code entity e.g.
SigningKeysForm partial view should have its own JQuery/JQueryUI scripts.
Which means any view which renders this partial view should include JQuery/JQueryUI script files.
Also another issue is when a view is composed of several such partial views, it means the javascipt in the partial views will be in several locations in the generated html.
My current approach to these problems is exploiting the top down parsing of views in ASP .Net MVC.
For tackling first problem I define a HtmlHelper extension to include a script e.g.
<% Html.RequireScript(Scripts.JQuery); %>
This way in each partial view and view I explicitly call out which scripts are required. The implementation of this method is to create a HashSet on current HttpContext and add the required script there.
In my master page I have another HtmlHelper extension which checks the HttpContext and renders the script include tags e.g:
<%=Html.RenderScriptIncludeTags()%>
This way I can track the requirements of views and render only the required script includes.
For the view scripts I am employing a similar approach. I use a custom Asp .Net user control which instead of rendering its content stores the script content into a buffer on HttpContext e.g:
<mvc:script runat="server">
$(function(){
alert("Hello " + "<%=Model.Name%>");
});
</mvc:script>
Again in the Master view I have a HtmlHelper extension which minifies (if needed) the stored scripts and renders them e.g:
<%=Html.RenderScripts()%>
</body>
I think this works as a solution, but it requires the script includes and scripts to be in the bottom of the master page. This means the script includes are not in the head section.
I want to know if there are better ways to manage the script requirements and in view page scripts with ASP .NET MVC.
Have you thought about using an existing tool that does this sort of thing, like Cassette (previously called Knapsack)?
Cassette automatically sorts, concatenates, minifies, caches and versions all your JavaScript, CoffeeScript, CSS, LESS and HTML templates.
I haven't personally used it (yet), but it looks pretty good, and seems like it should do exactly what you need (and more). Worth noting there is a small cost for commercial use.
EDIT: Now released under MIT licence :)
Telerik has a script registrar utility that does exactly what you are doing.
http://www.telerik.com/help/aspnet-mvc/web-assets-working-with-javascript-web-assets.html
As a bonus, it also does compression.
Yes it renders the scripts at the bottom.
Personally I usually include a few important scripts on the top the usual way and the rest with the scriptregistrar. That way I can have some scripts available during the loading of the page.
The telerik script registrar is part of their MVC suite.
http://www.telerik.com/products/aspnet-mvc.aspx