After reading from http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification :
The bundling framework follows several common conventions such as:
Selecting “.min” file for release when “FileX.min.js” and “FileX.js” exist.
Selecting the non “.min” version for debug.
[..]"
But :
even though my js files are not all minified in the solution, I still receive a minified version in the web browser when BundleTable.EnableOptimizations = true.
My questions is :
Why should I manually minify my JS files when the BundleTable.EnableOptimizations = true option take care of it ?
There's typically no reason to. Occasionally, I've seen certain scripts choke after being minimized automatically, and in those cases, it might be beneficial to use the minified version provided by the developer. Otherwise, it doesn't matter.
Also, you don't need to set BundleTable.EnableOptimizations = true. That's merely to force minification and bundling in development, which you should not do unless you're explicitly testing the bundling and minification itself. Otherwise, leave the setting alone. In development, you'll get all the scripts separately so you can debug easily, and in production, they will automatically be bundled.
Related
We're using script and style bundles to minify and bundle our resources. We're also using the StyleTransformer to transpile our .less files to .css.
coreCsss.Transforms.Add(new StyleTransformer());
coreCss.Include("~/Content/Common/Styles/core.less");
We also have a processor directive to only enable optimisations when building a non-debug configuration.
#if DEBUG
BundleTable.EnableOptimizations = false;
#else
BundleTable.EnableOptimizations = true;
#endif
The intention of the above is to allow us to more easily debug unpackaged and unminified javascript during development.
The problem we have noticed is that with EnableOptimizations disabled, then our .less files are not being transpiled and instead the raw .less is being served to the browser. Is there anyway to disable minification and bundling but still enable transformation? I would guess this is a fairly common scenario.
First, the code you have is completely unnecessary. Out of the box, EnableOptimizations is false in development and true in production. The only reason you might need to set it to something is if you actually wanted to enable the bundling in development (where it's disabled by default). That said, bundling is an all or nothing affair, if StyleTransformer depends on the bundling process to function, then if will have to be enabled in development, or you'll get exactly what you have.
Personally, I would recommend using something like the Web Essentials Visual Studio Extension, which among other things, will auto-compile LESS into CSS on save. Then, you can work with the LESS, and simply reference the CSS version. I'm sure there's other extensions with similar functionality. You can also set up build tasks to run gulp and such, but that's a little more complex.
Bundle works fine but does not update no matter what, even when I change the bundle structure by altering sequence of "Includes", adding "?xxxx333" [some dummy version] to file names, deleting files name from the includes. Changed contents of files. I even tried changing file name of an includes javascript file in the bundle includes, then renamed the file name in actual folder. App threw "File not found" error.
Not sure what to do. The bundle is just stuck and wouldn't change. I browsed around to find solutions. Others people experienced similar issues in the past but their solutions didn't work.
This is just crazy, I have change SriptsBundle to Bundle (so that files are not automatically mimified), added BundleTable.EnableOptimizations = false. Turned off the machine several times. Changed file names... nothing has worked. I guess my last resort is to get rid of this bundling and go back to explicit includes in files. I am just getting tired of these half cooked APIs being thrown into the market.
Any ideas?
Finally, what seemed to work is this :
bundles.Clear()
bundles.ResetAll()
Only issue now is I can't stop the bundling from mimifying everything despite the fact I am calling Optimization = false.
I had a similar problem. In my situation, I had a CSS file that changed (alongside the minified version) but the bundle would not update.
I noticed that there was a CSS mapping file also included in the project (even though the project on my development environment was set up to minify the CSS file but not generate a mapping file). Deleting this mapping file actually caused the bundle to refresh correctly.
I also had another issue once where I had a CSS file that was referenced in a script bundle but a minified version of that file did not exist. Even though I had the "EnableOptimizations" flag set to false in the bundle code, for some reason, the absence of that minified CSS file caused the script bundle reference in the MVC view to not update, even though it referenced the actual CSS file, not the minified version. Even after I got this working by including a minified version of that CSS file in the project, the reference in the MVC view still pointed to the original CSS file.
Long story short, the bundling code has some weird quirks (or features?) so you might have to try different combinations of things to get it to behave correctly.
So that I could take advantage of all the already well developed front-end tools like requirejs, bower and grunt... It's just that so many of them somehow get crippled going with rails.
Primary advantages:
It is easier to load third party scripts this way. It is always possible and sometimes easy to put these through the asset pipeline, but it is also often tedious and you lose bower.
Scripts in public will not be digested, so they can be loaded by non-rails pages easily. For example, you use a javascript file on your site, and also need to load it on another, e.g., PHP site, or need to allow other people to load your script for an embedded API, etc... then you'll need to serve from public.
Primary disadvantages:
Because you're not using the asset pipeline you lose:
Asset combining and compression. Asset pipeline CSS and Javascript will be loaded in a single HTTP request each, and the content can be minified. This makes first page load on your site faster, especially if you have lots of client code or a site that needs to be super snappy for occasional visitors.
Digesting. The asset pipeline protects you 100% from cache vagaries and potentially having different users seeing your site with different version of your assets. Once you deploy, every visitor will get the new assets.
Relatively automatic etagging. Once those visitors get the new assets, their clients will generally cache them for a long time. Rails can afford to let assets cache essentially forever because digesting ensures you're not punished for this later.
So there are pros and const both ways and neither is right or wrong.
It's just that so many of them somehow get crippled going with rails
Pipeline
The reason is you're not meant to use the likes of Grunt etc with Rails. Rails' asset pipeline is only meant to contain the files which can be precompiled & used directly in your application:
The asset pipeline provides a framework to concatenate and minify or
compress JavaScript and CSS assets. It also adds the ability to write
these assets in other languages and pre-processors such as
CoffeeScript, Sass and ERB.
This will typically mean compiled third party JS/CSS files, and your own application JS/CSS files. I don't see how something like Grunt would provide any benefit to this? All it does it create a way for you to manage dependencies, versioning & source of particular assets?
--
Public
Using the files in your public folder isn't such a big deal. One of the most prominent things it does do is to exclude those particular files from the file digest processs, allowing you to use the likes of endpoints (scripts) which can be accessed by other services (outside the scope of routes.rb)
A good example of this is when we created an analytics system, and put the analytics.js into the public folder, so all the widgets could access it. This allowed other sites to access this file, regardless of the state of the asset pre-compilation.
One caveat to this would be you could perhaps have some way to store a "pseudo" file in the public folder, with it routing dynamically (with ERB) to the precompiled equivalent, but I've got no experience with this
--
Pipeline
The benefits of keeping your assets inside the asset pipeline, as stated by gwcoffey, are:
They will be compiled as you design (I.E primarily into application.js, but also into any other files you define too)
You don't need to worry about versioning (every precompile is basically a way to better the version without worrying about grunt etc)
You can include as many dependencies as you want - meaning you're able to create a totally modular set of assets which can be used throughout your app; rather than single scripts which will have their own dependency base
Recommendation
Unless you maintain third-party scripts which need dependencies to run, I would not recommend using Grunt for Rails. If you develop your own JQuery / Javascript scripts, by all means run them through Grunt etc; but for use in your app, I'd steer clear
Hope that helps!
Is the included bundle tool in MVC good enough?
Is their any big reason not to use it?
I been working with squishIt in webforms and never been any problem. But now im on a MVC project and i've seen that MVC has it own bundle mecanism.
So should I use that instead?
Can it minify and gzip? Does it add any hash on the merged file as squishIt does?
Or is there any other solution on making the file unique on release?
Or is there any other one to use?
To answer your questions
Yes it minifies / gzip
Yes it adds a querystring to prevent caching
And (not a question), but Bundling also works with webforms
I would recommend using whatever you feel most comfortable with. The built-in bundling is fine though and easy to use, and has nice features for debug/live deployments.
I HAVE found that the minifier doesn't minify as efficiently as some others, though this usually isn't an issue as it will use the .min file if one is provided.
Say your bundle includes all scripts in a folder, and that folder has jquery.1.10.2.js and jquery.1.10.2.min.js, it will use the unminified file in debug mode and it will use the .min version in release mode. Then if you remove the .min file, in release mode the bundle will likely be slightly larger, but the end result will still be a minified bundle.
More Reading on the ASP.NET Bundling
And yes there are other packages, like YUICompressor. You can search NuGet for them, but I've always used the built-in bundling so can't speak to how good they are.
I discovered a really strange thing with the order of the output.
Im using those files:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Content/Script/json2.js",
"~/Content/Script/jquery-1.10.2.min.js",
"~/Content/Script/jqueryMobileCustom.js",
"~/Content/Script/jquery.mobile-1.3.2.min.js"));
The folowing output will be:
<script src="/Content/Script/jquery-1.10.2.min.js"></script>
<script src="/Content/Script/json2.js"></script>
<script src="/Content/Script/jqueryMobileCustom.js"></script>
<script src="/Content/Script/jquery.mobile-1.3.2.min.js"></script>
That's wrong!
But if I change the name of "jquery-1.10.2.min.js" to this: "jquery.1.10.2.min.js". It work's as it should. And ordering them as I want.
Do you know if there is a way to disable sortorder when using scriptbundle and include? Or why even does it react on a ' - ' instead of a ' . ' in my files.
I know it is a 'BundleFileSetOrdering' function but I like to specify it with a include.
I have started development of simple rails application. After several hours work I have notices that somehow the deleted css is still applied to the web pages.
In order to fix the issue I executed the following actions several times:
stop/start server
use rails server
use torquebox server
delete browser cache
but nothing changes. It was very strange - the new css definitions were applied, but those that I have deleted were still there. So, I gave up and decided to create new project.
I have setup the new project (its scaffold is the same as the first one) and when I open one of the views, the styles from the old project were applied too. I have decided to look again into http://guides.rubyonrails.org/asset_pipeline.html and find out that setting
#Expands the lines which load the assets
config.assets.debug = false
solves the issue. But what is this option doing exactly? Why the old projects css were applied when this was true?
This option's effect is well described in this post, but I'll summarize it here as well. The value of changing config.assets.debug lies in a compromise between page load time in development and ease of debugging.
Basically:
config.assets.debug = true: assets are served individually, organized just as you see them in development. Preprocessed languages like SASS or CoffeeScript will still show up as their target languages (i.e., CSS and JS, respectively).
config.assets.debug = false: assets are bundled into files like application.css and application.js. Error stack traces will likely not have the correct line number any more and it is harder to map those back to your original code.
If you get to this web page, there is a possibility you are here because you are using the Rails Asset Pipeline and you made changes to one of the javascript files and reloaded the page and the change is not reflected when you search in the Sources tab in Chrome.
As stated above, config.assets.debug = false prompts the Sprockets gem to bundle all the individual javascript and css files into one application.js and application.css respectively. Also Sprockets runs the the SASS and CoffeeScript (if you did not use --skip-coffee) preprocessors on all associated files to generate css and javascript files that the browser can understand.
One important note is the following. Ruby Guides says this about debug = false:
Assets are cached on the first request after the server is started. If
any of the files in the manifest have changed between requests, the
server responds with a new compiled file.
This means if you do not change the css or javascript files between requests, then a cache will be used. As soon as you change a file, the cache is invalidated and a new cache is created for subsequent requests.
Consequently, if you made changes to a javascript file and the change is not reflected on page reload, it has nothing to do with this option config.assets.debug.
There is this other option called
config.action_controller.perform_caching.
But by default this option defaults to false in development. That is, by default, caching is only enabled in your production environment. And in current versions, Rails only ships with Fragment Caching by default. You have to install separate gems for Page and Action caching.
Fragment Caching allows a fragment of view logic to be wrapped in a cache block and served out of the cache store when the next request comes in. But then again, cache fragments will also be expired when the view fragment changes (e.g., the HTML in the view changes).
So the question remains why is the change of your javascript not reflected? The answer is Google Chrome, the browser itself, is caching the page despite your Rails settings. To remove the cache, close the current tab, open a new tab, and visit the site again.