Looking for an advise on bundling of JS - asp.net-mvc

I have an MVC 4.5 project that has most of the UI logic organized in jQuery plugins. I want to protect my code by minification and bundling (While I understand that minification will only do so much as far as protection, it's better than leaving formatted and documented source files on the server.)
Ideally, I want my dev server to work as is -- files are non-minified and separated. But, when I deploy to the production server, I want the source files to be removed and only minified bundles to be available. Also note, on many occasions my jQuery plugins load other plugins from JavaScript code (I use head.js), so I cannot use #Script.Render for that.
What technologies do I use -- built-in MVC bundling, SquishIt, Bundler or do I need to resort to MSBuild and Microsoft Axaj Minifier? To recap, I want to remove source JS files and just be left with minified bundles in production, and, preferably, find a way to not change head.js references based on whether files are minified or not.
Thanks for your advice.

Just thought I respond with what I ended up doing here:
To recap: I wanted to obfuscate my source files with minification while not exposing the source JS files in production. I also wanted for head.js to resolve source file URLs to bundle URLs:
Put all non-minified javascript files in a folder viewable only to Admin role
Used bundling built-in to ASP.NET MVC 4.5 to generate bundles
Pointed my head.js tag to an MVC controller that returned head.js code + a javascript array with an x-ref between raw URLs and bundle URLs (available from BundleTable static object)
Bundling occurs outside of ASP.NET membership, so bundles are generated and available to anonymous users even though the source files are in the folder only accessible by Admin. Then, the trick of dynamically augmenting head.js code with server-side generated bundle URLs takes care of calling bundles from JS files.

Related

What is the equivalent of StyleBundle and ScriptBundle in node.js/expressjs/ejs?

I'm working on a project for my web applications course. One of the requirements for the project is to use the MEAN stack (mongo, express, angular, node). I also use EJS as the view engine.
I'm new to node, mongo and express, but I do have a lot of experience with ASP.NET MVC/WebAPI.
In ASP.NET MVC there's a library called System.Web.Optimization containing StyleBundle and ScriptBundle classes. One can create a bundle and add stylesheets/scripts to it, then link it to the view with Scripts.Render("path/to/bundle") (or Styles.Render(...)), which, depending on the app's configuration, would be replaced with either links to every file in the bundle, or a single link to a server-generated file containing the contents of all files inside that bundle, minified.
Is there an equivalent of this functionality in node/express/EJS? For the project I'm not really interested in the auto-minification functionality (but it could be good to know), but more in the bundling mechanism.

Vendor libs in ASP.NET MVC file structure

I'm the client-side guy at my job and for the web application we're building I am introducing some new JS libs besides the already residing jQuery and jQuery UI. We use the standard folder structure setup with CSS and images in ~/Content and JS in ~/Scripts. In the latter we have our internally developed libs categorized into subfolders such as ~/Scripts/Plugins.
However, now I want to add i.e. TinyMCE and find myself confused. NuGet installs all TinyMCE-related files to ~/Scripts/tinymce, but tinymce/skins holds CSS and images which I feel should not be contained in the ~/Scripts folder.
What is the proper way to structure vendor libs within the MVC file structure? Or, if there is no proper way, is there a proposed best practice? I don't feel like * up the original neat structure too much. Note that I am not looking for creating bundles, that lies in the future and the on-disk structure is a separate concern.

Loading an MVC JS bundle externally

I have a small JS library in my MVC 5 project that I want to be available for external users to load into their apps. At the moment I'm bundling it like so:
bundles.Add(new ScriptBundle("~/clientApi")
.IncludeDirectory("~/Api/clientapps/", "*.js"));
I can then access the bundled library via browser at the path /clientApi.
However, it's always minified, even though I've set my web.config debug=true, and other bundles in my own app are included as non-minified.
How can I make the file/s in the bundle available as a non-minified bundle file?
If you access /clientApi directly then yes it will be the bundled/minified version.
The debug=true option effects your script reference in your own .cshtml file. When debug=true, references to the individual script files are rendered to the client (so the client doesn't use /clientApi at all).
When debug=false, then a reference to /clientApi (with the version query string) is rendered to the client instead, so they get the bundled/minified version... If you give that link to these external users, then that is what is going to get rendered.
That path doesn't care if it is debug or not. It's not like /clientApi is going to bundle but not minify the files depending on your compilation settings... it's just either your app is going to render the bundled/minified path or the individual script paths.
If you want to do debugging/testing in external apps, then they will just have to use the individual script paths.
Even if you do give these external apps the /clientApi reference once testing is done and they are ready to use the bundled/minified version, it doesn't explain how you are going to handle versioning. If you update a script, how will they know to stop caching?
Actually you can serve the bundle unminified if you disable the transforms of the Bundles
protected void Application_Start() {
BundleTable.EnableOptimizations = true; // Force bundling to occur
// If the compilation node in web.config indicates debugging mode is enabled
// then clear all transforms. I.e. disable Js and CSS minification.
if (HttpContext.Current.IsDebuggingEnabled) {
BundleTable.Bundles.ToList().ForEach(b => b.Transforms.Clear());
}
}

MVC 4 bundled scripts does not reflect my changes to the script files

I have a MVC 4 application in .NET 4.0. My web hosting provider (network solutions) has virtual directories setup so I can't use the default bundling behavior (I think).
In my _Layout view I have this line:
#Scripts.Render("~/bundles/dd-d2")
In BundleConfig.cs I have
bundles.Add(new ScriptBundle("~/bundles/dd-d2").Include(
"~/Scripts/dd-d2.js"));
And everything works fine when I run in visual studio. But when i upload to my web hosting, The file is not found because it appends the virtual folder in front of the bundle path.
instead of /bundles/dd-d2?v=BlahBlah, I get /ROOT_FOLDER/bundles/dd-d2?v=BlahBlah
I fixed this issue by adding this to my line in the _Layout file
#Scripts.Render(Url.Content("~/bundles/dd-d2"))
The Url.Content helper converts the virtual path into an app absolute path and it finds my bundled script files.
Now, the problem I am having with that approach is, if I make a change to the javascript file, it is NOT reflected in the outputted bundled script file. It always has the old information in it even when I upload it to my web hosting. Is this file cached somewhere? Is there a better way of doing this? I would like to take advantage of the minification of my script files by using bundling.
if I do it this way, it does work
<script src="#Url.Content("~/Scripts/dd-d2.js")" type="text/javascript"></script>
But then my script is not minified.

Basic Bundling, Minification in ASP.NET

ASP.NET MVC 4.0 application - Visual Studio 2012
I cannot get bundling and minification to work in release mode.
My basic non-understanding is:
Do I have to provide the *.MIN.css, *.MIN.js files beforehand, or should VS minify the files on its own? (ie: I provide a mcimagemanager.js and VS makes a mcimagemanager.MIN.js out of it) ???
Here is a code snippet - which gets called in Global.asax:
public static void RegisterBundles(BundleCollection bundles)
{
var im = new ScriptBundle("~/bundles/MCImageManager").Include(
"~/Scripts/tinymce/plugins/imagemanager/js/mcimagemanager.js"
);
bundles.Add(im);
}
it works fine in Debug - not in Release-mode
Thank you!
No you don't need to provide .min file, nor will the bundler create that version (not something you see in the folder, at least).
The difference is this. Let's say you have both jquery-1.9.1.js and jquery-1.9.1.min.js in your scripts folder.
Debug mode will use jquery-1.9.1.js as the source script, and no it won't be minified or bundled, as the whole bundling/minification is disabled in debug mode (though you can override this).
Release mode will use jquery-1.9.1.min.js AND bundle it with other scripts for that bundle.
If you only have the one file, jquery-1.9.1.js, Release mode will use it and minify and bundle it.
Debug mode will NOT use .min files. So if you use a wildcard to include all files for a scripts directory, your .min files will not be included.
Debug mode, if you look at the rendered HTML, will reference all script files in the bundle individually. In Release mode, there will only be one script reference (with a querystring for versioning) per bundle.
Other relevant reading/posts:
Scripts.Render using outdated javascript file
Force ASP.Net MVC Bundle to render the javascript files in a certain order
Bundling and minification framework do also minification itself. So you just provide plain JavaScript/CSS files. It handle on the one hand files itself in the other hand it handle the registration in the view, for eample: #Scripts.Render("~/bundles/jquery"). So it "know" what file needs to be included in the view, weather it is "normal" or "min" version.
More on that topic you can find in this nice Exercise: http://msdn.microsoft.com/en-us/vs11trainingcourse_aspnetandvisualstudio_topic5.aspx
However this is might even better resource for the MVC oriented application: http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

Resources