gruntjs - usemin y reescribiendo urls de imágenes en archivos CSS de proveedores usando Grunt
yeoman grunt-usemin (6)
grunt-usemin me ayuda a transformar
<link href="/dependencies/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="/dependencies/nanoscroller/bin/css/nanoscroller.css" rel="stylesheet" />
<link href="/dependencies/dropzone/downloads/css/dropzone.css" rel="stylesheet" />
a un js perfectamente combinado y minificado:
<link href="scripts/8e1991c7.libraries.js" rel="stylesheet" />
Después de concat, cssmin y uglify tengo una estructura de carpetas casi perfecta a excepción de las imágenes y sus ubicaciones.
Aquí está mi problema:
Todos los archivos css de este proveedor incluyen ubicaciones de imágenes. Lo malo es que todos comparten diferentes tipos de ubicaciones. Algunos de ellos están usando imágenes dentro de la carpeta css mientras que otros están usando la carpeta img dentro.
¿Cómo puedo configurar el grunt usemin para reescribir todas las imágenes urls?
Investigué un poco y encontré un par de tareas que parecen terminar el trabajo: https://github.com/yeoman/grunt-filerev y https://github.com/richardbolt/grunt-cssurlrev . El único problema con esto es que tendrás que configurar las rutas dentro de tu Gruntfile manualmente, así:
grunt.initConfig({
filerev: {
images: {
src: [''img1.png'', ''img2.png''],
dest: ''tmp''
}
},
cssurlrev: {
dist: {
src: [''public/css/*.css'']
},
}
});
Que yo sepa, no hay un complemento que haga esta tarea automáticamente.
Tuve que implementar una nueva tarea. Esta es mi implementación preliminar.
grunt.registerMultiTask(''rewriteCssUrl'', ''rewrite url in css'', function () {
var options = this.options({
assets: grunt.filerev ? grunt.filerev.summary : {},
postFilter: function identity(input){ return input}
});
var self = this;
var assets = options.assets;
self.filesSrc.forEach(function (file) {
var css = grunt.file.read(file);
var original = css;
css = css.replace(/(?:src=|url/(/s*)[''"]?([^''"/)]+)[''"]?/s*/)?/gm, function (match, src) {
var key = path.join(path.dirname(file), src);
var asset = assets[path.normalize(key)];
var val = options.postFilter(asset);
return match.replace(src, val || match);
});
if(original !== css) {
grunt.log.writeln(''✔ ''.green + file + ('' was changed.'').grey);
grunt.file.write(file, css);
}
});
});
He resuelto el problema usando lo siguiente.
useminPrepare: {
html: ''src/index.html'',
options: {
dest: ''build'',
flow: {
html: {
steps: {
js: [''concat'', ''uglifyjs''],
css: [''cssmin'']
},
post: {}
}
}
}
},
cssmin: {
options: {
root: ''src''
}
}
Primero, estamos anulando el flow
useminPrepare
, eliminando la tarea concat de los flujos css. Esto es necesario porque concat destruirá la información de ruta relativa. Como cssmin se combinará con múltiples archivos, la tarea de concat con sepearte solo es dañina. ( https://github.com/yeoman/grunt-usemin/issues/225 )
Por último, le estamos diciendo a cssmin
dónde está la "raíz" de su proyecto del Gruntfile. Esto ayuda a cssmin
reescribir las URL relativas que encuentra en relación con este directorio "raíz".
Mi enfoque para este problema consistía básicamente en crear un styles/select2/select2.css
por styles/select2/select2.css
para cada estilo de proveedor, y luego Grunt puede copiar todas las imágenes relevantes en styles/select2
(sin tener que preocuparse por rutas relativas ni sobrescribir, etc.) como parte del guion Es decir:
app / index.html
<!-- build:css(.tmp) styles/select2/select2.css -->
<link rel="stylesheet" href="bower_components/select2/select2.css">
<!-- endbuild -->
Gruntfile.js
Agregue una nueva tarea de copy
que copiará los estilos de proveedor en el directorio .tmp
antes de que se minimicen con cssmin
:
copy: {
// this copies bower_components/*.css into .tmp so they can be compiled
styles: {
expand: true,
cwd: ''<%= yeoman.app %>'',
dest: ''.tmp/'',
src: [
''styles/{,*/}*.css'',
''bower_components/**/*.css''
]
},
dist: ...
Y luego, una vez que estén minimizados, copie los activos relevantes (que en este caso asumo que son solo imágenes PNG y GIF):
// and once we have compiled all of our stylesheets, we need to also copy over any necessary image files
distAssets: {
expand: true,
cwd: ''<%= yeoman.app %>/bower_components'',
dest: ''<%= yeoman.dist %>/styles'',
src: [
''**/*.png'',
''**/*.gif''
]
}
},
Finalmente, agregue las nuevas tareas en la tarea de build
:
grunt.registerTask(''build'', [
''clean:dist'',
''replace:dist'',
''copy:styles'', // -- added
''useminPrepare'',
// ... etc ...
''copy'',
''rev'',
''usemin'',
''copy:distAssets'' // -- added
]);
1) Imágenes rev. Agregue rutas de imágenes a la tarea rev.
rev: {
dist: {
files: {
src: [
''<%= yeoman.dist %>/static/scripts/{,*/}*.js'',
''<%= yeoman.dist %>/static/styles/{,*/}*.css'',
''<%= yeoman.dist %>/static/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'',
]
}
}
}
2) Agregue rutas de archivo que incluyan ubicaciones de imágenes en la tarea usemin.
usemin: {
html: [''<%= yeoman.dist %>/{,*/}*.html''],
css: [''<%= yeoman.dist %>/static/styles/{,*/}*.css''],
options: {
assetsDirs: [''<%= yeoman.dist %>'',''<%= yeoman.dist%>/static/images''],
}
}
3) Ejecutar gruñido.
Lo que me solucionó la aceleración de la background-image
CSS fue agregar un patrón de CSS en las options
, que busca todas las referencias de activos en el CSS y las reemplaza con los activos con revoluciones.
// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
...
...
options: {
...
...
// This is so we update image references in our ng-templates
patterns: {
js: [
[/(assets//images//.*?/.(?:gif|jpeg|jpg|png|webp|svg))/gm, ''Update the JS to reference our revved images'']
],
css: [
[/(assets//images//.*?/.(?:gif|jpeg|jpg|png|webp|svg))/gm, ''Update the CSS to reference our revved images'']
]
}
}
},