Bundle some CSS:
<%= Bundle.Css() .AddCss("~/css/jquery-ui-1.8rc3.css") .AddCss("~/css/CodeThinked.css") .RenderCss("~/css/combined.css") %>
CSS also has support for .less now. Any css file that ends in .less will be run through the .less compiler:
<%= Bundle.Css() .AddCss("~/css/testdotless.css.less") .RenderCss("~/css/combined.css") %>
How To Use Bundler
So, how do you get it working? Well, go to GitHub and download the beta from the downloads page. Then, all you need to do is reference the Bundler.Framework.dll from your website. Then just throw the code in that I provided above. You will just put the files in the order you want them in, and they will be minified or compressed and then combined into the an output file and written to disk where you specify. Once a file is written to disk, it is then cached and fed back over and over. The output will look like this:
Where Do We Go From Here
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.
Very good Job.
I can contribbute with this.
Good update, thanks.
Cool library. I have been looking for a library like that to integrate in my websites. All the ones I tested have some problems and had to remove them. Will test this soon and see
Very good job !
For the css Bundler, the attribute media of the link tag (all, print, screen …) is missing.
@Benoit Thanks, I’ll get that fixed up! It definitely needs to be able to be specified.
I can’t seem to get this working using relative paths "~/Scripts/Test.js" does not render as "http://localhost/scripts/test.js" but rather "~/Scripts/Test.js".
Am I doing something wrong here?
@Stephen Did you download the binaries? If so, I made a fix that I hadn’t included in the latest download. Just go grab the new binary that I put up on the GitHub downloads page and let me know if that fixes your problems.
Have you considered using DateTime instead of hash in the CSS and JS combined file? Hash looks a little bit ugly…
@Sergejus The hash looks ugly, but DateTime would not work across servers.
I am adding support for named groups of files, so that you’ll define the files somewhere, give them a name, then render them by just calling the name and not writing out each file. Will this let you accomplish what you want?
Ya, I understand order is important in case of js files. but, I don’t think order is important in case of css files. I am not sure of .less files though. I think the scope of less variables is only the current css files.
Can you please explain the approach. You are thinking of where will you define that these files belong to this group.
What, I am trying to accomplish is to deliver 24 css in one request.
and a bunch of js files in one request.
The files don’t get proccesed if isDebuggingEnabled is true. But so how do you preview your DotLess files while developing your website?
Also if debugging is on it will return the normal <link> tags with all the normal css files. But the href of those link tags returns with "~/" in the path.
Like in the example project you get this:
But html doesn’t understand the "~/" which results in broken links or am I missing something obvious?
Not sure if my comments need to be approved first or that my previous comment got destroyed. Just wanted to say that the questions I had were already fixed in the newer version on Github.
Very handy library you created Justin. Keep up the good work.
why don’t you allow both features like, appending a whole directory or individual file. If the developer thinks that order is important he can consider the way it is done right now. What i am talking about is something like
and it can be done including the sub directories.
considering that order is not important.
@Mohit I was thinking something along these lines for this syntax:
Put this somewhere like Global.asax in app start:
Then in a page, when you need to render this bundle, just call this:
Would this work for you?
Thanks a lot justin for your response. I could use the way you were telling me. Only issue is, we use a compiled application class, so it is not in global.asax.
along with that,I was reading following lines.
As per your following post
and if the ordering file is not specified. then just add it alphabetically. I think this will satisfy my requirement. My requirement is simple specify the directory and all files are added, if order is specified use it else don’t use it.
Justin, I really appreciate your so frequent response.
@Mohit I’ll look at it and see how hard it would be to get some of that back in there. I’m not sure currently that any of it is working, but the infrastructure is still there.
Right now my focus is on getting the code base more testable, since originally I had no plans of ever releasing this. Now that it has grown a tiny bit, a few bugs are popping up which could have been easily prevented with better unit tests. Just goes to show that even the smallest applications need to be easily testable, especially if you don’t have a lot of time for development. 🙂
very sweet and delicious article.
Tastes like ice cream!
Thanks for releasing this. Previously, I had done this via an MSBuild task, but this is more full-featured and easier to integrate.
A couple of suggestions, though. The CssBundle and JsBundle classes seem to perform caching by using a static Dictionary instance, with the Render() methods first inspecting that dictionary before attempting to render the file.
(1) It would be nice if the Render() method tested for the file’s existence even if the cached entry appears in the dictionary. This avoids the overhead of rehashing or regenerating the file but would also help sanity check situations where someone deleted the generated file for whatever reason. Not a big issue but nice to have.
(2) If this is run in a Web site that runs under n worker processes on the same machine (a Web garden), the file will get regenerated and rehashed n times, since each process will have its own (empty) Dictionary instance and the Render() method does not check for file existence. While you could add support for out-of-proc caching, that seems overkill, so a simple does-the-file-already-exist-if-so-hash-it-and-cache-it in the Render() would also solve that problem.
(3) If generation fails for whatever reason (permission problem, missing jar file, etc), it would be nice if it auto-reverted to the debug mode behavior instead of throwing the exception. This one is certainly a stylistic preference and I’m sure I’ll get some flames on this one =)
Thanks for taking the time to post this!
1) Excellent point, I’ll make this change. Can you submit it as an issue on the GitHub issue tracker?
2) Hmmm, I see what you are saying, but how would you know if the file was the latest version, or if it was an old leftover version of the file?
3) I’ll see what we can do in this case, but I’m not sure what action I’ll take on this.
2) You wouldn’t, but I see where you are coming from. I think it is probably a result of trying to accommodate two incompatible workflows … that is, caching a hash of the file versus just using the file’s existence as an indicator of whether or not it needs to be regenerated. I’ve usually taken the approach that if the file exists, use it, if it’s not there, re-generate it (and to get it to update you would delete the generated file, which would usually happen as the site is uninstalled/reinstalled as part of a WiX installation package). But I see the use case that some people want to be able to edit the CSS file and then recycle the app pool to clear out the cache. (The alternative being editing the CSS file and then deleting the generated file, no recycling/restart/cache.Clear()/whatever required.)
It is perhaps moot because in a multiple Web server setup, we are probably not going to be editing CSS files individually anyway, instead depending on a deployment mechanism like Windows Installer. (Indeed, since I use a Windows Installer uninstall/reinstall to roll out updates, the generated files don’t get reinstalled as part of the upgrade process, letting them get generated on the first hit.) But if one were doing an xcopy-style deployment where a generated file might get copied over, one would probably expect that file to get re-generated. (In that case, wouldn’t the last-modified timestamp be good enough, a quick run through of all of the constituent files’ timestamps compared to the generated file’s? That would work across copies among compatible file systems.)
I reckon that neither philosophy is more correct than one or the other, only to note that the one chosen has an unfortunate side effect with Web gardens. I think it’s perfectly reasonable in this case to note the limitation and say "who uses Web gardens anyway, if it bothers you pre-generate the file as part of your deployment process."
Hmm, I suppose I see now why they say cache management is one of the hardest things to deal with 😉
Look here how I did just that 😉
Leave a comment