ASP.NET MVC 4 Bundling - Individual File URLs in DEBUG mode - c#

Problem:
In the HTML5 offline app being done in ASP.NET MVC 4.5, we are bundling and minifying the styles and scripts using the framework's built-in feature. Everything working well with the pages themselves, but for writing into the Cache Manifest, where (because of the we we are writing it) it is always only emitting the bundled URL.
And so, we are not able to debug JavaScript in the offline mode, as the individual debug js files are not getting into the application cache.
Code:
RegisterBundles
This is how our BundleConfig.RegisterBundles look:
// For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/Scripts").Include(
"~/Scripts/*.js"
));
}
HTML Markup
And we include it in our _Layout.cshtml for the pages itself like this:
#System.Web.Optimization.Scripts.Render("~/bundles/Scripts")
This works well for the pages, by emitting the individual js files when debug is true, and one bundled file when debug is false.
Output in debug=true
<script src="/Scripts/ScriptOne.js"></script>
<script src="/Scripts/ScriptTwo.js"></script>
<script src="/Scripts/ScriptThree.js"></script>
Output in debug=false
<script src="/bundles/Scripts?v=B0_RvAM_5ifnREcGnNQ3FO8qQp4vyLOdtCUJ-2mXSuA1"></script>
Cache-Manifest
And this is how we include the scripts into our CacheManifest
#System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/Scripts")
Output in debug=true and debug=false
/bundles/Scripts?v=B0_RvAM_5ifnREcGnNQ3FO8qQp4vyLOdtCUJ-2mXSuA1
What we want?
We would like to know if there is a way we could get the Cache-Manifest to be output like this:
Output in debug=true
/Scripts/ScriptOne.js
/Scripts/ScriptTwo.js
/Scripts/ScriptThree.js
Output in debug=false
/bundles/Scripts?v=B0_RvAM_5ifnREcGnNQ3FO8qQp4vyLOdtCUJ-2mXSuA1

The MSDN documentation talks about a certain Scripts.RenderFormat method, which looked like a good candidate for doing what we want. But intellisense was complaining this RenderFormat method is not present in the version of System.Web.Optimization currently referenced.
But, thanks (once again) to Google, this answer here on SO was explaining that this RenderFormat method is in fact, included in the next version's alpha release. And the comment on that answer linked to the page that explains how we could install it:
PM> Install-Package Microsoft.AspNet.Web.Optimization -Pre
With this version, the Cache-Manifest could be changed to:
#System.Web.Optimization.Scripts.RenderFormat("{0}","~/bundles/Scripts")
And we now have the cache manifest emit the individual files while debug=true.
Apparently, the MSDN documentation is not in sync with the current stable release !

Related

How to disable Browser Link in ASP.NET Core (.NET 6, VS 2022)

I have disabled Browser Link inside Visual Studio 2022, and I have also disabled all the Hot Reload functionality.
Even the Browser Link Dashboard indicates it should be disabled:
I also do not use any of the app.UseBrowserLink(); code anywhere in my code. (as documented in Browser Link in ASP.NET Core.
However, these middlewares still somehow appear in the request pipeline:
Microsoft.AspNetCore.Watch.BrowserRefresh.BrowserRefreshMiddleware
Microsoft.WebTools.BrowserLink.Net.BrowserLinkMiddleware
These middlewares add this to my HTML:
<!-- Visual Studio Browser Link -->
<script type="text/javascript" src="https://localhost:44399/0928d478a97d441187231f2a1a7cd5e5/browserLink" async="async" id="__browserLink_initializationData" data-requestId="c94cf93088fb44e98f4e499b20ad7bfe" data-requestMappingFromServer="False"></script>
<!-- End Browser Link -->
<script src="/_framework/aspnetcore-browser-refresh.js"></script></body>
And every time I save a file, it reloads the browser. I want to stop this behaviour, and I ran out of options how.
Is this something that the IIS Express or Visual Studio add automatically?
I also checked all the packages and DLLs, and I don't see it included anywhere in my code. It must be included automatically via some "magic" that Visual Studio 2022 does.
How do I stop all this reloading? I do not want any Browser Link or Browser Refresh. Please help, I spent a lot of time on this, and I'm desperate.
You are almost there. You just need to also config the following (Don't forget to restart your VS):
Visual Studio uses .NET Core's Startup Hook feature to inject those middlewares, if you set a breakpoint on the first line of your Program.cs and evaluate System.Environment.GetEnvironmentVariable("DOTNET_STARTUP_HOOKS") in the debugger, you can see which hooks are getting loaded from where. If you now go and rename the files it's trying to load, it won't be able anymore to do that and you're free from browserLink!.
For example, in my case, it was loading
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\Extensions\Microsoft\Web Tools\Browser Link\Microsoft.WebTools.BrowserLink.Net.dll"
"C:\Program Files\dotnet\sdk\6.0.201\DotnetTools\dotnet-watch\6.0.201-servicing.22124.17\tools\net6.0\any\middleware\Microsoft.AspNetCore.Watch.BrowserRefresh.dll"
so i renamed them, adding a _ in front of them which made the script injection disappear.
More needed to uncheck!
This is really hard to unroot feature.

.NET bundling/transforming not working even with forced manual configuration

I had a previously working local configuration that is not bundling even with forcing the settings.
This is happening on both JS and CSS bundling.
Example code only
private static List<string> ScriptBundleExample
{
get
{
return new List<string>()
{
"~/Assets/javascriptfile1.js",
"~/Assets/javascriptfile2.js",
};
}
}
// separate function
var bundle = new ScriptBundle("~/Bundles/javascript-example");
ScriptBundleExample.ForEach(script => {
bundle.Include(script)
}
bundles.Add(bundle);
I have appropriately added the render in my layout:
// different casing to above but never mattered
#Scripts.Render("~/bundles/javascript-example")
I have forced the setting here which should be bundling correctly:
Note: This setting overrides the debug setting within Web.config yet it still doesn't work with both overrides.
BundleTable.EnableOptimizations = true;
I have also turned off any debugging in Web.config (both in wwwroot and the project file):
<compilation debug="false" targetFramework="4.7.2" />
FWIW minifying also isn't working:
bundle.Transforms.Add(new JsMinify());
Previous related questions on SO
MVC Bundling Not Working
The OP worked on the assumption debug="true" was the correct setting which it was not.
Bundled scripts not working MVC
This was a minification issue which is not the case here.
MVC Bundle not working with Release Configuration (Debug is False), CSS and JS not loading
I'm not getting 404 errors because the bundling isn't working but the proper files are still coming out the server as individual scripts (as if I'm always in debug mode) so the files are being included correctly.
ASP.NET MVC Bundle not rendering script files on staging server. It works on development server
This person just didn't understand the bundling and minification process.
WebGrease package exists in my solution.
Why is my CSS bundling not working with a bin deployed MVC4 app?
Same as above, the OP did not understand how these settings worked. I do not have a .js extension in my bundles.
https://stack247.wordpress.com/2013/02/08/mvc-bundle-not-working-with-release-configuration-debug-is-false/
Not in SO but this didn't work.
Everything I did above was correct from a C# point of view. Through running some breakpoints, I realised that the code was bundling correctly but was being overridden by another setting in the pipeline after the one above executed which set BundleTable.EnableOptimizations to false and unbundled everything.
So for anyone reading ahead, if you set the same settings as above, you've done everything right to bundle it from a C# perspective. Check through debugging that the setting is not being overwritten elsewhere.

Bundle Scripts in Angular with MVC

In my shell page "index.html", I need to include all the necessary files (js, css, etc).
Sample :
<!-- 3rd party libraries -->
<script type="text/javascript" src="scripts/angular.min.js"></script>
<script type="text/javascript" src="scripts/angular-route.min.js"></script>
<script type="text/javascript" src="scripts/angular-resource.min.js"></script>
<script type="text/javascript" src="scripts/angular-animate.min.js"></script>
<script type="text/javascript" src="scripts/angular-ui/ui-bootstrap.min.js"></script>
<script type="text/javascript" src="scripts/angular-ui/ui-bootstrap-tpls.min.js"></script>
In existing MVC with razor project, I can bundle this files like this :
bundles.Add(new StyleBundle("~/app/controller").Include(
"~/app/controllers/placesExplorerController.js",
"~/app/controllers/usersController.js"));
In addition, what are techniques can I use to load only the needed files. Not to load all (In SPA). Lazy load artifacts
Update:
Just saw you edit the question that you want specifically lazy loading. Then go for ocLazyLoad.
ocLazyLoad is awesome in a sense that you can inject the $ocLazyLoad at almost anywhere you want.
myApp.controller("MyCtrl", function($ocLazyLoad) {
$ocLazyLoad.load('mySciprt.js');
//if you want to load more than 1 file, pass in an array:
//$ocLazyLoad.load(['myScript.js', 'myStyle.css'])
});
You can also use a directive:
<div oc-lazy-load="{['js/testModule.js', partials/lazyLoadTemplate.html']}">
<!-- Use a directive from TestModule -->
<test-directive></test-directive>
</div>
And you can couple it with your ui.router too, if you are using it:
$stateProvider.state('index', {
url: "/", // root route
views: {
"lazyLoadView": {
controller: 'AppCtrl', // This view will use AppCtrl loaded below in the resolve
templateUrl: 'partials/main.html'
}
},
resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
// you can lazy load files for an existing module
return $ocLazyLoad.load('js/AppCtrl.js');
}]
}
});
oclazyLoad Docs
I am assuming you want a more performant AngularJs app, and that you are using a .NET environment (MVC projects, IIS servers, etc). Allow me to provide you some options:
Option 1 - Stick to Razor's Bundle
Razor's Script bundle actually allows you to minify your Javascripts and your CSS files. Just add in BundleTable.EnableOptimizations = true; and you will have your JS and CS files minified on built. Depending on your project, this might serve as a good solution. Usually an .NET's MVC4/5 project is most suitable to use this method, as they by default use cshtml and Razor syntax's too. I won't recommend this for an rich Angular app though.
Option 2 - Use Gulp or Grunt In conjunction with MVC project
If you do not know it, Visual Studio can now run a NodeJs application. There are even Task Runners that allows you to use grunt/gulp in VS. This is just perfect as now you can use your favourite IDE to build front end apps.
For me, I will create an empty MVC web project, organize my own folder structures, let the IIS hit my index.html and let angular handle the rest. The MVC project itself does nothing but just provide me a web.config so that I can host it in IIS. I run my gulp and grunt, do the minification and build tasks, and dump them into release folder, configure my web.config to let my IIS listen to my sub directory, and voila - I just seperated out development codes and production code.
This option is a good choice because I get the best of both worlds. I can run gulp and grunt - which gives me the freedom to write my own build tasks. You can use bower-install or npm-install too, but just remember to include the files in your project. On the other hand, I can still use VS as my IDE, and by default this is still an .NET project. A .NET project will comes in handy when you want to deploy to Azure (biased opinion though).
Option 3 - use ocLazyLoad
If you are really talking about serve the files only when they are needed, then it's lazy loading. For this, if you do not want to use require.js, look into ocLazyLoad module. One of the best project ever. This allows you to load your html, js and css files lazily, and you got the freedom to choose when to load them.
Hopes this helps.
To bundle, you would typically use a tool like Grunt or Gulp to concatenate the files into bundle-like structures.
To load only the needed files, a popular tool is RequireJS which lazy loads modules based on routing.

Bundle knockout.js in ASP.NET Web Application - VS2013

I'm trying to add a bundle for Knockout in my application. From NuGet, I got two scripts:
knockout-3.0.0.debug.js and
knockout-3.0.0.js
I'm using the following code.
bundles.Add(new ScriptBundle("~/bundles/knockout").Include(
"~/Scripts/knockout-{version}.js"));
For some reason, it will include the "debug" version:
<script src="/Scripts/knockout-3.0.0.debug.js"></script>
My question:
How can I get the non-debug version?
(I have tried running in both debug and release configurations, with the same result)
Best regards,
Thomas
Unless EnableOptimizations is true or the debug attribute in the compilation Element in the Web.config file is set to false, files will not be bundled or minified. Additionally, the .min version of files will not be used, the full debug versions will be selected. EnableOptimizations overrides the debug attribute in the compilation Element in the Web.config file
more info

Can I minify JavaScript or aspx code in Microsoft Visual Studio 2010

I'm developing a web app using C# and MS VS 2010 IDE. The project has several of my own .js files in the Scripts folder that are designed to run on a client-side browser. While writing them I gave each variable and function in the JavaScript meaningful names and used plenty of comments.
So I was wondering, can I minify those .js files before publishing them (or uploading to a production web server) in Visual Studio 2010?
PS. It would be also helpful to minify aspx files as well...
There are several libraries listed on the NuGet Gallery for minification.
They will all deal with javascript and css, but none will minify the aspx markup.
Hope this doesn't sound like too much of a commercial but I do recommend my own OSS project RequestReduce. It minifies and merges CSS and JS files (or any css or js mime typed file) on the fly at run time (caching them of course). It also generates optimized sprites of most css background images. Currently it does not minify html but that is on my backlog. The features that make RequestReduce stad out from the rest is that it does not require any code changes and extremely minimal configuration. In fact if you are using nuget, there may be nothing more to do than install the package. It also works with CDNs and web farms. It has been adopted by many of the MSDN and Technet web applications (forums, search, galleries). I have seen some page load times cut in half using this. And of course it is absolutely free.
I don't think it will do everything your looking for but I like to use Chirpy. You can find it at:
http://chirpy.codeplex.com/
It is really easy to use to minify js, css, and combine them into one file. It will also minify js and css in the aspx file.
Look at the documentation page and follow the three links (reverse order is better) to see what it can do.

Categories