ASP.NET MVC: versioning static scripts (outside of bundles) - asp.net

In my ASP.NET app, I have several pages/scripts that I can't bundle - PDF.js viewer page or MediaElement video loader.
But sometimes I do minor amendments to those scripts; I need to version/cache-bust the respective script files, so these are auto-reloaded for users. In PDF.js viewer.html, for example:
<script src="viewer.js?v=1.1"></script>
The gotcha is: how to make ASP.NET/IIS auto-inject the version info into the static HTML files that it serves? Any solutions?
Thank you in advance.

Do you use any type of task runner?
I use Gulp, and whenever I build, I have a task to replace my version number with something unique to ensure the latest version is always requested.
So in my Index.cshtml:
<script type="text/javascript" src="~/bundle.js?v=$$VERSION" charset="utf-8"></script>
And in my gulpfile.js:
gulp.task('version', function () {
return gulp.src('index.html')
.pipe(replace('$$VERSION', Date.now()))
.pipe(gulp.dest('dist'));
});

Related

How do I remove livereload script from release build?

I'm a backend developer messing with a f/e app for a short while and I'm using grunt to watch-livereload my changes.
What is confusing to me is that, to make the livereload work, I have added a script tag to my index.html
<script src="//localhost:35729/livereload.js"></script>
But I don't really want that script to go into my production, I'm guessing no one want's that either.. how are people dealing with this?
Should I remove the tag from the page manually before I build every time?
It doesn't look like a great way to go about it, seeing as how grunt is all about automating tasks.. is there a way to automate this task too?
All I want is to remove the script before publishing for release.
I'm using a simple angular.js app if that matters.
thank you
You can use grunt-dom-munger to process the index.html on the build grunt task that you use for deployment.
Your script include in index.html will look like this:
<script src="http://localhost:35729/livereload.js" data-remove="true"></script>
and in the grunt file you will have (in the dom_munger section):
update: {
options: {
remove: ['script[data-remove!="false"]', 'link[data-remove!="false"]']
}
}
This way you will have full control over your index.html before deploying it, just read the docs on don-munger.

Including angularjs into existing web forms project

I am trying to include angularjs framework into a existing web forms application. But I am not able to access the angular directives from the aspx pages. I am sure there is some part of settings that I am missing. I added the angularjs package using the nuget installer. It created a directory "Scripts" and dumped all the angularjs related files. Can any body help me in putting up the settings correct so that I can make use of angularjs directives on the apsx pages.
Thanks in advance for the help and suggestions.
Include the script:
<script src="angular.js" type="text/javascript"></script>
Add ngApp to the body tag:
<body ng-app="app">
...
</body>
In your script define your module:
<script>
var app = angular.module('app',[]);
</script>

Referencing files minified by Web Essentials in Visual Studio 2013

I have minified CSS and JS files that are auto-generated by Web Essentials, and auto-updated every time I update and save the original files.
What would be the best way to automatically toggle the actual (script/import) references within HTML between original (in Dev/Test) and minified (in Production) files?
This is within an MVC ASP.NET web app.
One idea would be to have server-side tags that render either ".min" or empty string based on an environment variable. But I'm wondering if there's a better, smarter, easier, more efficient way of handling this.
Thanks in advance.
Update:
My style bundle is defined like this:
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site{version}.css"));
And I reference it like this:
#Styles.Render("~/Content/css")
However, this renders the following:
<link href="/Content/css?v=" rel="stylesheet"/>
It works fine if I take "{version}" out of bundle definition, but renders an empty "v=" if I include "{version}".
Update 2:
I just realized that due to certain complexities of the application, I can't use the bundling solution. What other options do I have?
Bundling will help you in this instance. You should already be able to see an example in your BundleConfig.cs file in App_Start.
Here is a tutorial on how to conifgure it http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
From that tutorial, this is how you actually configure the bundles themselves, the files that will be in them, etc. This includes any jquery in the scripts folder into a bundle called ~/bundles/jquery.
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
// Code removed for clarity.
BundleTable.EnableOptimizations = true; // <-- this line overrides the debug check to show you the minified version even in debug mode... remove it for normal .min in debug/un-minned when not in debug behaviour
}
You then reference these from your views using
#Scripts.Render("~/bundles/jquery")
This will then render a script tag with the .min version of the jquery if you're not in debug or leave it out if you are. There needs to be a .min version and an un-minified version in the same scripts folder (which you should have if Web Essentials is creating the .min for you.
You could actually stop using Web Essentials to do the minification if you use ScriptBundles as they will minify the javascript for you when it packages it into the bundle.
For your update
The "~/Scripts/jquery-{version}.js" means match any file in the scripts folder that starts with jquery- and ends with .js and has some version number between. If the files don't have a version number in them, then don't try and use the {version} substitution.
They do it with jquery in this case so that if you upgrade the version of jquery that you are using, you don't have to go back into your BundleConfig and manually change the file name for your jquery reference.
If your file was named site1.3.7.css, then this would probably work.
bundles.Add(new StyleBundle("~/Content/css")
.Include("~/Content/site{version}.css"));
but it sounds more likely that you just need site.css.
bundles.Add(new StyleBundle("~/Content/css")
.Include("~/Content/site.css"));
I'm not sure what you think prevents you from using them but you can link to files in CDNs and minify or not minify. Even just have individual files in a bundle to get the benefit of minification outside of debug without "bundling" them. So there's probably a way.

ASP.Net MVC Bundler not including my .min file in Release

I have an issue with the mvc4 bundler not including a file with extension .min.js.
In my Scripts folder i have two files: bootstrap.js, bootstrap.min.js
In my BundleConfig class, I declare
#if !DEBUG
BundleTable.EnableOptimizations = true;
#endif
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include("~/Scripts/bootstrap.js"));
When running in Debug it renders as expected:
<script src="/Scripts/bootstrap.js"></script>
When running in Release it renders as:
<script src="/bundles/bootstrap?v=57XuMf8ytOYgVErEDhgFDRtQ5jlC48bryka4m2DVq_M1"></script>
Why doesn't it render as:
<script src="/Scripts/bootstrap.min.js"></script>
Why doesn't it render as: <script src="/Scripts/bootstrap.min.js"></script>
Because that's how bundling works in ASP.NET MVC 4. Don't worry, the contents of this /bundles/bootstrap?v=57XuMf8ytOYgVErEDhgFDRtQ5jlC48bryka4m2DVq_M1 is exactly the contents of the /Scripts/bootstrap.min.js. In this case the bundling mechanism hasn't minified the /Scripts/bootstrap.js file but used the already minified version.
The reason you want to use bundles.
Declare one statement but generates multiple import resources codes.
Minify your js or css code
Bundle mutiple files into one file which will reduce the browser
request number.
Bundle will give the request url a suffix which is generated based on
the files. So if you don't cache the page, there will be no js/css
cache problem, you don't need to clear browser cache.
By default, when you're in debug mode (you can modify your Web.config to set if enable DEBUG), the js/css files will not be bundled, so you can see the files seperately which will make it easier to debug.
When it's not debug enabled, the files will be bundled.
So if you already have .min.js files, you can import them directly in your page.

Durandal Caching Issue / Versioning Strategy

What's a good strategy for versioning Durandal js and html files?
I noticed that, during development, your browser cache must be disabled in order for you to receive up to date files on each refresh. This is a must for during development.
However, my concern is that when I go to production with my continuous deployment strategy (deploying multiple times per day), that users' browsers will be caching older versions of my app which might lead to unpredictable behaviour.
The approach that springs to mind would be to version the js and html urls somehow so that there is a version number embedded into every request. But I am unsure as to how to make that work internally within the Durandal framework.
Ok, here is the direction that I am heading in. Basically there is something built into requirejs to handle this.
At the top of my main.js, in the call to requirejs.config I can set a urlArgs property that will be appended to every call requirejs makes for a module.
requirejs.config({
paths: {
'text': 'durandal/amd/text'
},
urlArgs: 'v=1.0.0.0'
});
When I want to force production users to get a new version of the requirejs modules I can just increment the version number which will invalidate the browsers cache.
(In my project I have a way of injecting the version number of the assembly containing my main ASP.NET MVC assembly into this property, but the code for that would have distracted from the simplicity of the above example).
Hope this helps someone!
For .NET, add the main-built.js file as a script bundle in App_Start/BundleConfig:
public static void RegisterBundles(BundleCollection bundles)
{
//...
bundles.Add(new ScriptBundle("~/Scripts/main-built").Include(
"~/App/main-built.js"));
//...
}
Reference the script bundle on your index page:
#if (HttpContext.Current.IsDebuggingEnabled)
{
<script type="text/javascript" src="~/Scripts/require.js" data-main="App/main"></script>
}
else
{
<!-- Remember to run the weyland optimizer to create the main-built.js -->
#Scripts.Render("~/Scripts/main-built")
}
As long as you have the default Web.Release.Config file, Visual Studio will automatically remove debug attributes while also minifying and versioning your bundles upon publishing.

Resources