Reputation: 850
I am trying to move frontend dependencies out of the version control system. A combination of Bower.io and Grunt should be able to do this.
A problem however occurs that I am yet unable to solve with bundling multiple vendor libraries. For example assume I have the following directory structure where the components directory is the directory that Bower.io saves the dependencies in:
├── assets
└── components
├── bootstrap
│ ├── img
│ │ └── glyhs.gif
│ └── less
│ └── bootstrap.css
└── jquery-ui
├── css
│ └── style.css
└── images
├── next.gif
└── prev.gif
Now assume I want to bundle both jQuery's style.css and Bootstrap' bootstrap.css. I will save this bundled file in assets/bundled.css.
However in this file the references to the original images (../images/next.gif and ../img/glyhs.gif) are incorrect. They will have to be rewritten in order to work (so ../images/next.gif => ../components/jquery-ui/images/next.gif). I believe(d) this rewriting of URLs is something Grunt should be able to do. But I can not seem to get this to work using the cssmin/less/copy tasks. For example the following Grunt setup (only moving 1 file) fails to work:
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
less: {
options: {
compile: false,
relativeUrls: true
},
bootstrap: {
src: 'components/bootstrap/less/bootstrap.less',
dest: 'assets/bootstrap.css'
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.registerTask('dist-css', ['less']);
};
Either:
Have I misconfigured Grunt or done something wrong?
Or is the workflow I am describing simply not the right one and should I use another one instead.
Thanks!
Upvotes: 29
Views: 15321
Reputation: 850
Just for reference: there is now a solution readily available. I posted this same issue to the CleanCss grunt plugin, and they have accepted it and published this behaviour in their new 1.1 release.
You can find the issue on the GitHub tracker here: https://github.com/GoalSmashers/clean-css/issues/129
This library makes it possible to either use absolute rewriting (from a root directory) or alter relative image paths based on a new output directory. Look for the --root
or --ouput
directives.
Thanks for the tips and answers people!
Upvotes: 5
Reputation: 870
You probably wat to take a look at this grunt package https://github.com/Ideame/grunt-css-urls. This package seems to be intended to solve exactly your problem.
Edit: after looking at this plugin I didn't like the idea of rewriting my markup in order to make my build process smoother. So I ended up writing my own tiny function which does the rewrite for me.
I use grunt's concat plugin for bundling my css files. Good thing about this plugin is that it suports file processing function before concatenation. Now my gruntfile looks like this:
grunt.initConfig({
concat: {
options: {
separator: '\n',
process: function (src, filepath) {
var cssPatt = new RegExp('app(\/.*\/).*\.css$');
//filter out everithing except css files
var file = cssPatt.exec(filepath);
if (file) {
var urlPatt = /url\(\'(.*)\'\)/g;
console.log('In file: ' + filepath);
//replace every url(...) with its absolute path
return src.replace(urlPatt, function (match, p1) {
console.log(' * ' + match + ' -> ' + 'url(\'' + file[1] + p1 + '\')');
return 'url(\'' + file[1] + p1 + '\')';
});
}
return src;
}
},
}
Upvotes: 6
Reputation: 10146
You'll want to do some search/replace on your dist css file to generate the correct relative paths. There are a number of grunt plugins that can do this for you, personally I prefer grunt-replace. Set up your non compressed assets with variables and then produce a dist css with the URLs dynamically generated.. So:
body {
background:url(@@IMG_PATH/background.jpg);
}
Becomes this in dist:
body {
background:url(path/to/background.jpg);
}
Hope this helps.
Upvotes: -2