I have been doing some performance analysis on a few websites I am working on and I am noticing that a big problem is the inline scripts. For the external scrips I wrote an http handler which combines, minifies, and gzips the javascript into one file. This is then stored for reuse later by hashing the filenames.
What I am wondering (not sure if this is a good idea but I am posting to get some feedback) is if I remove all script elements with script text inside them and combine them into a single file. I then use the same process I am using for the external scripts and combine them into a single script.
John
Inline script always gets inside the page so needs to be traversed by every post or get to and from the server. Since you're using MVC it's quite easy to only have non obtrusive script files in your project as you have quite some control over the rendered html.
You also want to check out SquishIt.
Grz, Kris.
It is possible to minify and bundle inline javascripts in with external files.
As I mentioned here Minify inline javascript during build for ASP.net?
With templated Razor helpers you could create an extension method like
the one below:
public static MvcHtmlString AddScriptSource(this HtmlHelper helper, Func<dynamic, HelperResult> source, string key)
{
string scriptSource = source(null).ToHtmlString();
// Cache scriptSource here
return MvcHtmlString.Empty;
}
Which you would use like this:
#Html.AddScriptSource(#<text>$(document).ready(function() { $('h1').text('The current controller is #ViewContext.RouteData.Values["controller"].ToString()'); });</text>, "test")
Related
I am using Knockoutjs in my asp.net MVC-5 application. I have the following javascript in view:
<script type="text/javascript">
var model = "#Html.Raw(Json.Encode(Model))";
$.get("#Url.Action("_CityPartial")" ...)
//any much more code using similar Html helpers + pure javacsript code.
</script>
Now i want to know, is there any way to transfer this javascript code in a separate js file (keeping Html helpers as it is).
I want to transfer javascript code to separate file because i dont want any user to check my javascript code (using chrome inspect element or any other way).
If the transfer is not possible than please let me know if there is a any way to minifiy the javascript in view itself ??
You could create an external .js file with your code in and pass your serialized json object to it like this:
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model));
DoThis(model);
</script>
This has the benefits of keeping the main body of javascript in a separate file.
Any other razor variables can be passed across to the methods defined in the javascript in the same manor as the model has been above.
However as Stanyer mentions this is still javascript and it will run on the client.
You can load it via an external JavaScript file, but unfortunately as JavaScript is a client-side scripting language regardless of whether its loaded inline or externally, the client can still view the code which is being executed on their browser.
You mention minifying - again this can still be interpreted by a client if they really wanted to see your code, but there are many tools online which can minify your JavaScript for you.
Examples:
http://jscompress.com/
http://www.jsmini.com/
No you cant keep the #Html helpers in external javascript file. They are all server side syntax and will be rendered in your HTML page inline.
What maximum you can do is, assign it in a var variable in your page and refer it inside a external page.
Background information :
A tool simulates IE behavior, instead of HTML for browser, it uses a special object which contains html segment<![CDATA[ HTML Here or JS here ]]>. The tool disabled the ajax call; however, the activeX works on that tool. In other words, HTML display in browser = special object display. No server side language (i.e. php) allowed.
Problem :
The object developed for that tool contains everything(html+css+js) in one single file. Then it makes developer difficult to manage changes. Currently, when I develop, I copied the HTML from <![CDATA[ All HTML or JS here ]]>; after I modified it , I copied the html file back to <![CDATA[ HTML Here or JS here ]]>. I want the object is more organized, for example: in the html segment of the object, just put something like <![CDATA[<javascript>require a.html<javascript> ]]> , then the content in a.html will be automatically placed in the object. Can you suggest any solution or any library for this problem?
ps: I didn't use requirejs before, it seems requirejs uses ajax call to include text file, is it possible that requirejs uses local path to include a file?
Thank you.
Partial solution to my problem: I used activeX to read the entire file, and used jQuery to set the file content to some html element. so the js will look like:
<![CDATA[
<script>var k = readfile(getAbsolutePath()+"\\a.html");
jQuery("#display").html(k);<script> ]]>
I think this solution is for my tool only; To make it work, some requirements:
1. can get the absolute path of the text/html file.
2. activeX works.
OK, now that I understood your problem.
Use
<iframe src="another_file.html">
That is probably the only way to load multiple html files without Ajax or PHP, as far as I know.
Per comment from prytsh, using an embed call should do the trick in HTML5:
You can try this by using jquery
//use this line in jquery
$("#id").load("trackingCode.html");
In my javascript files, I have too much hardcorded url that references controllers actions. Sometime, I also have messages displayed directly from my javascript.
What is the best way to remove all these hardcoded strings from javascript files?
Step one, use T4MVC to automatically generate a structured set
of .NET classes that describe your ASP.NET MVC's application
structure
Step two, create a new partial view that defines server-side
information described by T4MVC as a set of Javascript constants.
<script type="text/javascript">
var SHOPPING_CART_DETAIL_URL = '#Url.Action(MVC.ShoppingCart.Detail(Model.ShoppingCartId))';
var CLIENT_DETAIL_URL = '#Url.Action(MVC.Client.Detail(Model.ClientId))';
var USER_IS_ADMIN = #(User.IsInRole(Roles.Admin) ? "true" : "false");
</script>
Step three, include this partial view in the head of whatever page
you need it. You could also include it in the head of your general
page layout. Make sure this loads before the rest of your JavaScript files.
Step four, use your newly defined JavaScript constants throughout your JavaScript files.
For that purpose I use T4MVC. It will allow you to use strongly typed objects in place of literal strings. You will need to initialize your javascript in your views, but other than that it works great.
For messages etc. here are some ideas: what are the different approaches to multilingual javascript applications
If you want to avoid using T4MVC, you could make a Controller that parses JS files. Just configure a route in Global.asax that catches all the javascript urls, and that action will ready the JS file, parse it, return a result with the URLs.
routes.MapRoute(
"Javascript",
"{url}.js",
new { controller = "Javascript", action = "Parse" }
);
Then write an action that reads the requested URL, finds the JS file, replaces values based on a Key/Value dictionnary. Perhaps even externalize that Key/Value dictionnary if could need that. The rest is up to you.
Another option would be to use a controller action that returns Javascript code. That javascript code would be a list of variables filled with URLs that are MVC generated.
I'd like to build my own, but I'm not sure about the best way to do it. A partial is a template that is only a part of another bigger template and which can be inserted into multiple other templates at will.
Templating itself is fairly basic, just string exctraction and concatenation, but clientside partials have me a little stumped.
Here are a few methods I thought about:
1,
I could write a javascript helper function that loads partials through ajax into some form of local storage I suppose, and all subsequent templates that require that particular partial would first look inside local storage. I think this method isn't very safe because local storage isn't always guaranteed. And if I can't save them into local storage, partials would result in too many ajax calls.
2, I could put them all into script tags inside my main html file. This would work reasonably well, especially with head.js (to enable parallel loading of script tags), but still - I think each script tag is a separate call to the server right? That doesn't exactly improve the situation.
3, I could put all templates into a single script tag (or html I guess) and manually filter through some kind of delimiter...like: "#template1(blabla template1 string) #template2(blablabla template2 string) and put those strings into globals.
This would result only into a single call to the server, all the rest is done on the client.
Suggestions? I have looked at existing templating engines, but I can't really determine how they do it. The code is pretty complicated
The approach I took to spec out template calls and on-demand loads for the spec/rewrite of jQuery templates is to pipeline it.
See section 9 of the (early) draft spec, and see the conformance suite tests at the bottom for an example of custom on-demand template loading (Testcase "Main calls and Loaded just in time!" is the relevant one).
The basic gist is that plugin loaders (written in JS) get to hook in between-parsing and compiling to inspect the parse tree. A plugin pass gets an object mapping template names to parse trees. If they see any partial template selectors (to use your parlance) they can try and load any unresolved templates using AJAX calls or file I/O on Node.js, and add the partials to the input object to cause the compiler to compile the just loaded partials along with the public templates.
Efficiency-wise, see the benchmarks. I'm in the process of migrating the code to github : https://github.com/mikesamuel/jquery-jquery-tmpl-proposal in case you want to collaborate.
I have a partial view (UserControl) that implements a simple pager in my Asp.Net MVC project. This pager needs access to a .js file that needs to be included exactly once, regardless of how many instances of the pager control are present on the parent page.
I've tried to use Page.ClientScript.RegisterClientScriptInclude, but it had no effect (I assume because the code nugget was evaluated too late to impact the head control). Is there any simple alternative?
Set a flag in HttpContext.Current.Items when you send the script in your partial - it's a dictionary that lingers for the whole request. E.g.:
if (!HttpContext.Current.Items.Contains("SentTheScript"))
{
HttpContext.Current.Items["SentTheScript"] = true;
Response.Write(Html.ScriptTag("Script"));
}
This way it'll be rendered at most once.
Add it to the master page.
Then you can guarantee that it'll only be included once, and you won't forget it.With modern caching, there is really no performance loss on including it on every page.
Page.ClientScript.RegisterClientScriptInclude is used with the traditional ASP.net.
Since you using asp.net-mvc, all you need is to add the script directive of the js file to the page that uses this user control.
Since it's a good practice to have only one minified css file to all the site, you probably will want to include this file in the main css minified file.