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.
Related
I'm trying to figure out, whether I should be using config.assets.prefixin my development environment or not.
When I'm using localhost, for development, are there any (dis-)advantages of doing this? When the local server itself isn't caching and is on another domain (production-domain vs localhost), I fail to see the disadvantages? Especially for hard-coding some paths in CSS and Javascript, which will then always return 404's on development..
I've been using config.assets.prefix = "/dev-assets" as pr. reccomendation of another developer, who isn't working with us anymore.
Is this a problem, that anyone else have thought about and taken a standpoint at?
The biggest reason of using config.assets.prefix, emerges from the use of local asset precompilation. There are multiple reasons of precompiling locally and storing in source control. From http://guides.rubyonrails.org/asset_pipeline.html#local-precompilation
You may not have write access to your production file system.
You may be deploying to more than one server, and want to avoid duplication of work.
You may be doing frequent deploys that do not include asset changes.
Local compilation allows you to commit the compiled files into source control, and deploy as normal.
But if you use this, you will get into trouble in development mode because rails will serve your precompiled assets found in /public/assets. Therefore, you often set config.assets.prefix = '/dev-assets' so you don't need to precompile every time you want to see effects of local changes in /app/assets.
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.
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.
At a glance they seem to be pretty much the same solution to the same problem, but Jammit must have some key difference or improvement that I haven't picked up on, or its author would have just used asset_packager. :-)
Can anyone enlighten me?
Sure. Here's some of the main differences:
Instead of using simple Ruby-based CSS and JS minifiers, Jammit makes it easy to use either the YUI Compressor or the new Google Closure Compiler to compress your assets.
Instead of having to specify each file individually, Jammit uses an ordered list of directory globs to define an asset package. This means you can say things like: give me jQuery first, then everything in vendor, then all my models, then all my UI...
workspace:
vendor/jquery.js
vendor/*.js
models/**/*.js
view/workspace/*.js
Jammit supports JavaScript Templates, so whether you're using Prototype or Mustache or Underscore templates, you can maintain your JavaScript views right alongside your Rails views, and have them bundled into a single package, available in the browser.
Jammit supports image embedding, using Data-URIs for browsers that support them, and MHTML for IE7 and below. Enabling it allows you to embed all of your UI chrome and small icons right into your CSS, so that instead of 50 HTTP requests, your browser makes just one.
When you install the gem, Jammit includes the jammit command-line utility, which you can use to prebuild all of your assets and pre-gzip them at the highest compression level. Gzipping at --9 gives us about a 30% reduction in size for our assets, over the default gzip --2 (which is closer to what you'll get by default if you're gzipping on-the-fly). You should be using both, but only gzipping on-demand for dynamic requests.
Hope that helps with the differences -- for everything else, there's http://documentcloud.github.com/jammit/