I have an express app in which I'm using bower to manage the front-end dependencies. I'm also using grunt to build the front end by concatenating, uglifying, minifying, and rev'ing all the assets, including the scripts/styles that ship with each bower component using grunt-usemin
.
To accomplish this I'm moving all of the compiled assets (including bower scripts/styles) to a dist/public
directory. I end up with a <cache-buster>.vendor.js
and a <cache-buster>.vendor.css
file, which contain all of the optimized bower components.
The question is, how should I manage images that ship with various bower packages? I could manually move them into my images
folder, but I would prefer to leave them packaged in bower_components
(where they belong, in my opinion) and leave it up to grunt during the build process.
Any input would be appreciated.
Gruntfile.js (extract)
rev: {
dist: {
files: [{
src: [
'dist/public/css/{,*/}*.css',
'dist/public/js/{,*/}*.js',
'dist/public/img/{,*/}*.{gif,jpeg,jpg,png}'
]
}]
}
},
useminPrepare: {
options: {
dest: 'dist/public'
},
jade: ['dist/views/{,*/}*.jade']
},
usemin: {
jade: ['dist/views/{,*/}*.jade'],
options: {
assetsDirs: ['dist/public'],
patterns: {
jade: require('usemin-patterns').jade
}
}
},
concurrent: {
server: [
'stylus', 'coffee'
],
dist: [
'stylus', 'coffee'
]
},
copy: {
dist: {
files: [{
expand: true,
cwd: 'views',
dest: 'dist/views',
src: '{,*/}*.jade'
}]
}
}
});
grunt.registerTask('server', [
'clean:server',
'concurrent:server',
'express:server',
'watch'
]);
grunt.registerTask('build', [
'clean:dist',
'concurrent:dist',
'copy:dist',
'useminPrepare',
'concat',
'uglify',
'cssmin',
'rev',
'usemin'
]);
layout.jade (extract)
//-<!-- build:css(assets) css/vendor.css -->
link(href='/bower_components/nivo-slider/nivo-slider.css')
//-<!-- endbuild -->
//-<!-- build:css(.tmp) css/application.css -->
link(href='/css/one.css')
link(href='/css/two.css')
//-<!-- endbuild -->
//-<!-- build:js(assets) js/vendor.js -->
script(type='text/javascript', src='/bower_components/jquery/jquery.js')
script(type='text/javascript', src='/bower_components/nivo-slider/jquery.nivo.slider.js')
//-<!-- endbuild -->
//-<!-- build:js(.tmp) js/application.js -->
script(type='text/javascript', src='/js/one.js')
script(type='text/javascript', src='/js/two.js')
//-<!-- endbuild -->
Here is a solution adapted to your Gruntfile:
rev: {
dist: {
files: [{
src: [
'dist/public/css/{,*/}*.css',
'dist/public/js/{,*/}*.js',
'dist/public/img/{,*/}*.{gif,jpeg,jpg,png}',
'dist/bower_components/**/*.{png,jpg,jpeg,gif,webp,svg,eot,ttf,woff}'
]
}]
}
},
useminPrepare: {
options: {
dest: 'dist/public',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
},
jade: ['dist/views/{,*/}*.jade']
},
cssmin: {
options: {
root: 'src'
}
},
This assumes your bower_compontents directory is located in a source directory called 'src'. In my environment (bootstrapped with Yeoman) it was in 'app', so you may need to tweak cssmin.
Here is what is happening:
First, we add rev checksums to a bunch of possible resource files in the bower_components directory.
Next, the flow
configuration tells usemin to skip the concat
step for css files. This is because cssmin
does a concatenation itself, and cssmin
needs to know the origin of the css files in order to do the relative-path correction for referenced resources.
Lastly, the root
config tells cssmin which path to start searching from to find the resources.
You can check to verify the results are correct by going to dist/styles/<cache-buster>.vendor.css
and verifying the images have relative URLs, starting with /bower-components/
For example, in my build, I have bootstrap.css embedded in my vendor.css, and it has been rewritten like this:
@font-face{
font-family:'Glyphicons Halflings';
src:url(/bower_components/bootstrap/dist/fonts/2ad0632b.glyphicons-halflings-regular.eot);
(line wrapping added for legibility, its all cssminified in reality).
I hope this helps.
Giving credit where it is due, I found this originally here: https://stackoverflow.com/a/21415649/1017787 I've adjusted it to your configuration and added the revision config.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With