TL;DR: IItemTransform isn't getting executed when a minified file already exists in the same folder as the original (non-minified) file.
Problem explanation
I'm having this issue mainly because of CSS relative image references. If you used IItemTransform with Javascript files, the same applies.
This is what I'm using:
I'm using Visual Studio with Web Essentials addin to have support for LESS files
I'm writing LESS files and have Web Essentials addin automatically minify files on save
I'm also using bundling and minification in my project
When creating CSS bundles I'm using CssRewriteUrlTransform to make CSS URLs absolute (i.e. background images) so that images still work after bundling several CSS files together
Nothing unusual here so far, but it doesn't work.
What seems to be the problem?
The way that bundling and minification works is it tries to avoid excessive processing. This means that when a minified file exists in the same folder as the original one it won't run its own minification and rather serve existing file.
This would be all right as long as it would at least run transforms over those preexisting minified files. But it doesn't. So I end up with relative URLs in a bundle which breaks pretty much all those resources.
Workarounds
Always provide absolute paths in LESS files
Disable file minification on save in Web Essentials settings
Refer to minified files when defining my bundles because they don't have a minified version (*.min.css doens't have a *.min.min.css) so minifier actually picks up the file and minifies while also running transformations over it.
From the standpoint of my development process and tools used (and configured the way they are) this looks like a bug. If those files would be the result of the same minification process this wouldn't be a bug at all as transformations would be executed when minification would execute. It's true that such functionality doesn't exist and likely never will as app would need write permissions to make it work. Outcome: this is a bug. Existing minified files should be processed through transformations before being cached.
Question
Is it possible to somehow convince bundling and minification to either:
not use existing minified file versions
run transformations over existing minified versions
Have you considered using Grunt? http://gruntjs.com/
It has a learning curve, but, the information pool is huge. The issues that you are having with web essentials wouldn't be a problem with grunt.
I'm using it in VS, now, to minify, bundle and transpile both css and javascript as well as reorganize files into a deployment directory. Once you've set up a directory structure, a grunt file could very easily be reused.
With the add-on in VS (linked, below), you can right click on the grunt file and select the grunt tasks to run from a popup menu.
https://visualstudiogallery.msdn.microsoft.com/dcbc5325-79ef-4b72-960e-0a51ee33a0ff
Grunt "tasks" as they are called can be created by downloading various plugins i.e. https://www.npmjs.com/package/grunt-contrib-less.
I have never used LESS or web essentials, so please take this post for what it is worth (not much.) Could you add a pre-build command to simply delete the old files, then do a rebuild when you need to update the CSS.
Related
I'm dealing with an ASP.net project that's maintained by a couple of people via git.
We're looking to minify the CSS files at build time and have checked out the bundle and minify addon however this doesn't appear to offer an option for the minified code to be regenerated from the source files at each build.
Is there a better way for us to minify our source css files on each build?
Understanding your question right, you want to concat and minify your css sources and time you build or deploy.
I do not now how your build stack look like, so I can guess only, but using css files I would use something like grunt or gulp.
On my self I prefer gulp. It is easy to create a task which concat, minify or also auto prefix your css files.
Once your task is created you can add it to your build script, task or bash.
This way works also fine with CI like wercker or travis.
You can use Microsoft Ajax Minifier after build.
Explained here: https://www.codeproject.com/Articles/182690/Minify-Javascript-and-CSS-using-Microsoft-Ajax-Min
Or if you have integration with Jenkins then after build step you can call bat file and run minification on folder of your build directory.
For multiple technology projects, You can create exe based on Microsoft Ajax Minifier and after all builds are done, Run this exe using bat command from Jenking only to minify all the css and js files.
I have integrated this with PHP, ASP.Net and Silverlight code after build of these projects.
One better way is to make your file to online file (like CDN link github can help you in that) and next rather then adding all those css add that link which will be saving much of the build time.
Try to minify your file.
Try to make an online link file.
I'm currently working on a web-based project where we have a corporate branding style which overrides Bootstrap's default colours and styles via a .less file generating the .css for the stylesheet.
I've put a large amount of effort into making this .less file and would like to re-use it across projects but also allow it to be updateable in a single location rather than needing to copy the .less and generated .min.css and .css for each update.
I've tried linking each of the artifacts using "Add existing item" in VS2013 but the file is not available when the Web Application project is run.
Does anyone know how I would configure the project/file links in order to not have to copy the file between projects and update multiple files?
The easiest way to share variables, mixins, and other LESS elements, is to use #import. If the external shared elements are in an accesible path, you can directly specify the whole path in the #import clause.
However, sooner or later you'll use Grunt in your web pojects. It's a task runner, and the tasks are things like copying files, compiling less to css, minifying, and so on. This is widely use to manage the front end components of your application, specially css and js.
In your particular case, you could use grunt to copy the less file from the central location, and then run a less task to generate the final css, .min.css and, if you want it the corresponding .css.map, which is really useful to debug the styles from the browser's console.
If you want to use grunt for this case, basically you have to create two grunt tasks:
a copy task, to copy the file from the central location. This is optional but advisable if you #import your global colors .less file in each applciation's particular LESS file
a less task, that compiles the .less files into .css
The tasks definition is done in a simple json file, packages.json, and a js file, gruntfile.js. Althoug it can seem daunting, you can have it up an running in a few hours.
If you look for Grunt in Visual Studio Gallery you'll at least find "Grunt launcher" that allows to easyly run this tasks from within Visual Studio. In VS 2015 you can use Web Essentials (and it's probably a native functionality, but I'm not sure). There is also the "Task Runner Explorer" (see the last link below).
If you google "visual studio grunt", you'll find interesting info like this:
Using Grunt, Gulp and Bower in Visual Studio 2013 and 2015
Introducing Gulp, Grunt, Bower, and npm support for Visual Studio
Once you get used to it, you'll do a lot of things, like copying, compiling, transplining, concatenating, minifying, generating maps, etc. because this task runner has a lot of functionalities, and it's really easy to use.
NOTE: it's based on npm, which uses packages, in a similar fashion to Nuget, so you'll get the same advantages of using Nuget, but for front end artifacts. There are many packages available in npm which you will not find in Nuget
I want some expert advice on ASP.NET MVC Bundling and Minification. I have in my project script files that have both unminified (.js) and minified versions (.min.js). I have included them in my script bundle as follows:
bundles.Add(new ScriptBundle("~/bundles/layout").Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/lib/errorhandling.js",
"~/Scripts/lib/errorhandling.min.js",
"~/Scripts/vendor/modernizr.custom.js",
"~/Scripts/vendor/modernizr.custom.min.js",
"~/Scripts/toastr.js",
"~/Scripts/toastr.min.js"));
It seems that the bundle indeed contains only once each script file, not twice. I have confirmed this both for development and production. (As a side note, in development, that is, when debug=true, the bundles are not rendered but the files are included as separate script tags. This is the desired behaviour for me, as well.)
My questions are:
(1) Is this the best and recommended way to include already minified files for production setup and unminified files for development?
(2) Does ASP.NET try to minify the whole bundle in production (even though it is already minified)? If yes, what is the best way to prevent ASP.NET from trying to minify the bundle?
Thanks in advance!
There is no need to specifically include the minified versions in your script bundle. By default, MVC will search for a matching file with .min.js and include that (not entirely sure if it trys to minify further). If not, it creates a minified version. You can test this by adding the following to BundleConfig.cs
using System.Web.Optimization;
then adding the following at the end to override debug=true in development
BundleTable.EnableOptimizations = true;
From MS documentation
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.
Ignoring “-vsdoc” files (such as jquery-1.7.1-vsdoc.js), which are used only by
IntelliSense.
Minification, or not, the bundling feature is useful to for logical groupings of scripts and css that go together, and as a single place to control things. It also generates unique URLs, so eliminates browser cache problems.
If you use ScriptBundle, the engine will try to minify, (except when you set debug=true as you've shown).
You can turn off minification, but retain bundling, by just using Bundle() instead of ScriptBundle(). See Martin's answer here:
ASP.NET Bundles how to disable minification
As an aside, using pre-minified files with Bundle() as opposed to ScriptBundle(), will preserve the license headers. With jquery's MIT license, it at least stipulates that it should not be removed. I'm not sure how to interpret the fact that the default Microsoft MVC template uses ScriptBundle().
I'm considering using LESS for CSS development with server (or development) side processing, but I can't decide if I should keep the generated CSS files in version control. There are plenty of solutions with hooks, but this adds software dependencies to the server. A hook could just be added locally so staging and production areas on the web would get the same files. So, the question is:
Should generated CSS files be included in version control or not? Please keep in mind that some frameworks require a CSS file to exist for a particular reason (i.e. WordPress themes require a style.css file in order to be recognized).
When I say 'considering using LESS', I mean it becomes a requirement. New developers would not have the option use vanilla CSS after the choice is in favor of LESS.
Checking in derived artifacts is almost always sub-optimal.
I vote no to checking in the .css. It's only a matter of time until one of your peers or successors checks in an edit to the .css and not the .less. Then when you change the .less the prior change is lost.
You've pretty much answered your own question. It depends on how you deploy your website.
If the server is just going to pull directly from the Git repository:
1) It needs to have software installed to generate CSS from LESS.
2) or you need to include the CSS files in the repository.
If you're not pulling straight from the repository on your web server, you could have a build script that pulls from git, generates CSS, and then transfers the content to the web server(s), possibly excluding unnecessary files from the transfer.
In my opinion, Git should be used to keep all of the source for a project, and none of the "derived artifacts" (as mentioned by #thekbb). Developers need to have all tools installed to generate those derived artifacts during development and test. For deployment to test and production servers, an automated build server should take the source and create just the files needed for distribution.
In the case of software development, you'd have a Makefile with .C and .H files (for example) in your Git repository. Developers and the build server have a compiler installed that will create an executable or compiled library. When the files are packaged for distribution, the source code is not a part of the archive.
For web development, you have source files like original graphics, HTML templates and LESS files. Developers and the build server can run scripts to generate the site assets (CSS from LESS files, static HTML pages from templates, flattened images in multiple sizes/formats, etc.) When the build server deploys new builds, it copies just the files needed by the server, excluding the source graphics, templates and LESS files.
If there are people that need to review the site content, they should do it on a staging server. If that's not possible, the automated build server can create a ZIP file on an internal server that they can download for review.
Should generated CSS files be included in version control or not?
In theory they should not, but for practicality, I do usually checks in the generated css file. The reason is that it simplifies deployment since I do deployment using git; I would not need to have a less compiler installed on the server and usually not even on the machine I'm deploying from (as opposed to the machine where I'm developing on). Doing this could be useful if you have separate developer and deployer, but can sometimes also be useful even if you're deploying yourself.
Now, there are drawbacks on doing this:
You can't use git add --patch (or you really need to be very careful when doing so)
You should not modify the .css directly; instead I usually use a secondary .css file to do minor modifications without modifying the primary .less or .css file. You can also compile .less file straight into a minified css, to make it less tempting to modify the generated css.
Developers have to set up their machine to use automatic recompile tool (like SimpLess or Less.app), so the .css file is updated as soon as they save to the .less file. Without automation, you'll run into risk of the css not matching the checked-in less file.
I would not do the same when compiling from .C and .H files though, because the generated binary for those are platform specific, and also .less/.css file is usually a very small part of a larger web project so the space overhead of the additional file is small.
Good question. If you can absolutely guarantee that the CSS file gets updated when the LESS gets updated then perhaps yes - as per #Scott Simpson's comment. I suspect that this would be difficult to guarantee and what happens when the new developer get's a copy of CSS the day when they are out of sync? Also, of course, and I hadn't originally thought of this, what happens if the new developer then makes updates to the CSS file rather than the LESS?? If the CSS has to be built and isn't part of archive I can see less problems.
I would say yes -- because what happens if you want to add a developer to your workflow and they don't want or need to build .Less? It would be helpful for them to have access to only the generated file.
I'm using SquishIt and have a .less file which I add to a CSS bundle with the following line
.Add("~/content/styles/dev.less")
This compiles as dev.less.debug.css when I build the solution, however I'd like to be able to just save the .less file and it automatically compiles the css (so I see the change instantly in my browser as I would with a traditional CSS file).
I have looked at a number of extensions to achieve this (such as LessExtension and LessCssForVisualStudio) but these require the file to be added to the bundle as dev.css rather than dev.less. Mindscape Web Workbench does not compile LESS files in its free version so I do not know if it also requires dev.css.
I can't change the link to the file as the project will be worked on across teams, where some won't install an extension and will be happy to build the solution to compile.
Is there and extension that automatically compiles LESS that is built to work with SquishIt?
If you use it on non-production site, I would suggest using less.js (It will render css with js on client-side).
Squishit uses dotless under the hood, so you could use that directly.. either set it up so that you request the less file and a handler returns CSS or you can use the exe to compile on build and also the watch mode... I'm not sure what's best for you, but you can find more information on the dotless wiki (https://github.com/dotless/dotless/wiki/Using-.less)
Web essentials does this job perfectly and its free.
http://vswebessentials.com/