Grunt usemin task not updating nested relative paths correctly - gruntjs

I have a Yeoman project scaffolded with 'webapp-generator' which contains a static website with nested HTML files, resembling this structure:
-root/
index.html
-directory/
file1.html
-directory2/
file2.html
-js/
(revved .js files)
-css
(revved .css files)
I'm using usemin and filerev tasks to update the filerevved file paths on the .html documents. It updates all file names correctly on js/css/images and it works correctly on the root index.html.
However, on the nested HTML files, it doesn't replace the reference to the correct nested path.
For example.
js/scripts.js gets renamed to js/827385.scripts.js
In index.html
<scripts src="js/scripts.js"></scripts>
resolves to: <scripts src="js/827385.scripts.js"></scripts>
But in directory/file1.html (or any other nested html file)
<scripts src="../js/scripts.js"></scripts>
gets also converted to: <scripts src="js/827385.scripts.js"></scripts>
Ignoring the ../ relative path
Is there any way to tweak the Grunt tasks to be aware of the relative depth of the file within the directories to keep the relative indicator ../ in the renamed path?.
Below is the code snippet for the relevant Grunt tasks.
PS: I have already followed some of the possible answers in this Stack Overflow question: How should I configure grunt-usemin to work with relative path to no avail.
// Renames files for browser caching purposes
rev: {
dist: {
files: {
src: [
'<%= config.dist %>/scripts/{,**/}*.js',
'<%= config.dist %>/styles/{,**/}*.css',
'<%= config.dist %>/images/{,**/}*.*',
'<%= config.dist %>/styles/fonts/{,**/}*.*',
'<%= config.dist %>/*.{ico,png}'
]
}
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
// <%= config.dist %>
useminPrepare: {
options: {
dest: 'out',
// root: '<%= config.app %>'
},
html: '<%= config.app %>/index.html'
// root: '<%= config.app %>'
},
// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
options: {
assetsDirs: [
'<%= config.dist %>',
'<%= config.dist %>/images',
'<%= config.dist %>/styles'
]
},
html: ['<%= config.dist %>/**/*.html'],
css: ['<%= config.dist %>/styles/**/*.css']
},

In my case I've found out that the problem was usemin configuration in the html files:
If you have in your index.html this usemin directive:
<!-- build:js styles/jquery.js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<!-- endbuild -->
In directory/file1.html you should try to use a full path in it:
<!-- build:js /scripts/jquery.js-->
<script src="../bower_components/jquery/dist/jquery.js"></script>
<!-- endbuild-->
which will be converted to something like <script src="/scripts/jquery.34ad31c3.js"></script>.

Related

grunt build not concatenating bower_components

I am using yeoman webapp to scaffold a basic application. I use bower install --save to install a couple of libraries which make their way into bower_components folder. Now I run grunt build and to my surprise the index.html file in the dist folder refers to the bower_components folder for the js files. I had expected the build process to automatically concatenate these files and put the concatenated script in the dist folder and make the index.html file refer to this concatenated file. What should I do to make this happen by default.
Just facing the same issue on one of my project, a warning because of a bad file targeter was stopping the grunt build, and since the usemin task is the last to be run, my scripts was perfectly concatenated and minified, but the references in my html was not updated.
If you have like me an error, try to fix it or to run a grunt build --force to pass it.
If no, check that your scripts are correctly surrounded by the build tags
<!-- build:js({.tmp,app}) scripts/vendor.js -->
...
<!-- endbuild -->
And that you have correctly configure your rev, useminPrepare and usemin tasks
Little exemple :
rev: {
dist: {
files: {
src: [
'<%= yeoman.dist %>/public/scripts/{,*/}*.js',
'<%= yeoman.dist %>/public/styles/{,*/}*.css'
]
}
}
},
useminPrepare: {
html: '<%= yeoman.app %>/views/index.html',
options: {
dest: '<%= yeoman.dist %>/public'
}
},
usemin: {
html: '<%= yeoman.dist %>/views/{,*/}*.html',,
css: ['<%= yeoman.dist %>/public/styles/{,*/}*.css'],
options: {
assetsDirs: ['<%= yeoman.dist %>/public']
}
},
Also ensure that your build task is referencing to them :
grunt.registerTask('build', [
'clean:dist',
'bower-install',
'useminPrepare',
'concurrent:dist',
'autoprefixer',
'concat',
'ngmin',
'copy:dist',
'cdnify',
'cssmin',
'uglify',
'rev',
'usemin'
]);

Grunt usemin not replacing file references in sub directories or in compiled CSS file

I'm finding the grunt-usemin tasks a little confusing to set up. I'm using grunt-usemin to concatenate, uglify and rev my files. It is working for the root index.html file, however, files in other directories are not getting replaced with the revved file reference.
I have the following file structure:
app
index.html
subfolderA
--index.html
subfolderB
--index.html
assets
--img
--js
----script.js
--scss
----style.scss
On build, everything gets built into /dist directory.
My Gruntfile contains (among other tasks) the following:
useminPrepare: {
options: {
dest: '<%= yeoman.dist %>'
},
html: '<%= yeoman.dist %>/**.html',
css: '<%= yeoman.app %>/assets/scss/**.scss'
}
usemin: {
options: {
dirs: ['<%= yeoman.dist %>']
},
html: '<%= yeoman.dist %>/**.html',
css: '<%= yeoman.app %>/assets/css/style.css'
}
grunt.registerTask('build', [
'clean:dist',
'jekyll:dist',
'spriteHD',
'compassMultiple:dist',
'useminPrepare',
'concat',
'uglify',
'rev',
'copy:dist',
'svgmin',
'imagemin:dist',
'svg2png',
'modernizr',
'concurrent:replacementsDist',
'usemin'
]);
Blocks to be replaced in the HTML files look like:
<!-- build:js /assets/js/lteie8.main.js -->
<script src="//ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed.js"></script>
<script src="/assets/bower_components/selectivizr/selectivizr.js"></script>
<script src="/assets/bower_components/respond/dest/respond.src.js"></script>
<!-- endbuild -->
Once built, dist/index.html shows all the correctly revved file names - for css, js concat blocks and all images. However, the compiled CSS file does not contain the revved file references. Nor in all subdirectory index.html files do the file references get updated to the revved versions.
With me referencing the HTML files with **.html I thought that should target all html files in subdirectories. I presume I have some mistake in the usemin or useminPrepare task, is this the case?
== EDIT ==
In response to przno's answer I changed usemin:css: to <%= yeoman.dist %>/assets/css/*.css to get it to compile the CSS correctly.
With me referencing the HTML files with **.html I thought that should target all html files in subdirectories - use **/*.html

How to configure grunt's usemin:css task to rewrite rev'd images?

I'm building a site using the Yeoman generator: https://github.com/Thomas-Lebeau/generator-bootstrap-less.
I've installed fancybox using bower by doing the following:
bower install fancybox --save
add the fancybox script include into my usemin build block in index.html
#import "../bower_components/fancybox/source/jquery.fancybox.css"; into my only .less file
finally, copy across the fancybox vendor images using the following config in grunt's copy task.
code:
// Gruntfile.js
...
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'images/{,*/}*.{webp,gif}']
}, {
expand: true,
dot: true,
cwd: '<%= yeoman.app %>/bower_components/fancybox/source',
src: '**/*.{png,jpg,jpeg,gif}',
dest: '<%= yeoman.dist %>/bower_components/fancybox/source'
}]
},
...
(Sorry, don't know why the formatting is glitched there.. https://gist.github.com/ptim/8555923)
This is working for me, but I'd like to take it a step further to get a better understanding of what's going on. It's working simply because I'm replicating the relative path used in app/ when I copy.
What I'd like is to have the bower assets copied in with my other images, and the paths in my html rewritten (as happens with imagemin and usemin, etc)
....
}, {
expand : true,
dot : true,
cwd : '<%= yeoman.app %>/bower_components/fancybox/source',
src : '**/*.{png,jpg,jpeg,gif}',
dest : '<%= yeoman.dist %>/images'
}]
....
How do I achieve that using the conventions of this package?
(I've seen alternate suggestions: How to rewrite urls of images in vendor CSS files using Grunt)
I've tried changing the dest: path, and adding flatten: true
Here's the trail I'm following:
grunt build finishes with copy, rev, usemin,
rev is adding a version number to the fancybox files
usemin is executes usemin:html and rewrites all the image filenames to match the rev'd files
usemin:css then runs, but doesn't list any rewrites, then grunt finishes:
Running "usemin:css" (usemin) task
Processing as CSS - dist/styles/cf3b732a.main.css
Update the CSS with new img filenames
Done, without errors.
Can anyone suggest a tweak for me?

can't minify images using the grunt plugin grunt-contrib-imagemin

I just downloaded a fresh copy of yeoman. When I build using grunt, I see that all my images have been converted and their file names have been renamed.
However, the references in the html file do not reference the new names.
Any idea why?
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/img',
src: '{,*/}*.{png,jpg,jpeg}',
dest: '<%= yeoman.dist %>/img'
}]
}
},
usemin: {
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
options: {
dirs: ['<%= yeoman.dist %>']
}
},
ngapp/views/main.html
Renaming is done by the grunt-filerev task in your Gruntfile. The usemin task takes care of updating the references to those renamed files for scripts, stylesheets and images, but doesn't support inline styles. You should either move the background-image reference within a stylesheet or disable the rev task.
The problem is probably that your url for the image in your HTML file is a relative path and and usemin can't resolve the new path of the image to your url. See #eddiemonge comment on github for a better explanation: https://github.com/yeoman/grunt-usemin/issues/108
I had the same problem and fixed it by using a fixed path (/img/demo/red-green.png, in your case) which works fine as long as your distribution directory uses /img and img is also off the root of your app when doing development.

yeoman: how to compress components?

In yeoman application all my scripts are minified and compressed into single file, but all the "components" are copied as is which is an absurd - because it's a ~130 files in the starter project...
This what I belive is responsible for the concatenation task and the question is how to make it include my components which are mentioned in the index.html file? What parameters are to the files object are? Can't find anything in the documentation.
concat: {
dist: {
files: {
'<%= yeoman.dist %>/scripts/scripts.js': [
'.tmp/scripts/{,*/}*.js',
'<%= yeoman.app %>/scripts/{,*/}*.js'
]
}
}
},
I think what you're looking for is grunt-usemin.
When you include your components, you can wrap your <script> tags in <!-- build:js js/foo.js -->.
<!-- build:js js/main.js -->
<script src="js/carousel.js"></script>
<script src="js/index.js"></script>
<!-- endbuild -->
The useminPrepare task that's included in the package will cycle through any scripts within that block and add them to the concat/uglify task. Your task list might then include something like this:
useminPrepare: {
html: [ '<%= yeoman.dist%>.html' ],
options: {
uglify: 'uglify'
}
},
usemin: {
html: [ '<%= yeoman.dist%>.html' ],
options: {
basedir: 'dist'
}
},
Output to your foo.html would then be whatever you specify in the build comment. In my case, the scripts are concatenated, minified, and the reference to them is replaced with <script src="js/main.js"></script>.

Resources