gruntjs - uglify - ¿Por qué se recomienda utilizar concat y luego uglificar cuando este último puede hacer ambas cosas?
instalar grunt en windows (2)
Sigo viendo la recomendación de hacer que los archivos JS estén listos para la producción para que sean concat y luego verifiquen.
Por ejemplo here , en una de las tareas difíciles de Yeoman.
Por defecto, el flujo es: concat -> uglifyjs.
Considerando que UglifyJS puede hacer tanto la concatenación como la minificación, ¿por qué necesitarías ambas al mismo tiempo?
Gracias.
Ejecutar una prueba básica para ver si hay una diferencia de rendimiento entre la ejecución de concat
y luego uglify
vs. solo uglify
.
paquete.json
{
"name": "grunt-concat-vs-uglify",
"version": "0.0.1",
"description": "A basic test to see if we can ditch concat and use only uglify for JS files.",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-uglify": "^0.6.0",
"load-grunt-tasks": "^1.0.0",
"time-grunt": "^1.0.0"
}
}
Gruntfile.js
module.exports = function (grunt) {
// Display the elapsed execution time of grunt tasks
require(''time-grunt'')(grunt);
// Load all grunt-* packages from package.json
require(''load-grunt-tasks'')(grunt);
grunt.initConfig({
paths: {
src: {
js: ''src/**/*.js''
},
dest: {
js: ''dist/main.js'',
jsMin: ''dist/main.min.js''
}
},
concat: {
js: {
options: {
separator: '';''
},
src: ''<%= paths.src.js %>'',
dest: ''<%= paths.dest.js %>''
}
},
uglify: {
options: {
compress: true,
mangle: true,
sourceMap: true
},
target: {
src: ''<%= paths.src.js %>'',
dest: ''<%= paths.dest.jsMin %>''
}
}
});
grunt.registerTask(''default'', ''concat vs. uglify'', function (concat) {
// grunt default:true
if (concat) {
// Update the uglify dest to be the result of concat
var dest = grunt.config(''concat.js.dest'');
grunt.config(''uglify.target.src'', dest);
grunt.task.run(''concat'');
}
// grunt default
grunt.task.run(''uglify'');
});
};
En src
, he puesto un montón de archivos JS, incluida la fuente sin comprimir de jQuery, que se ha copiado varias veces, distribuida en subcarpetas. Mucho más de lo que normalmente tiene un sitio / aplicación normal.
Resulta que el tiempo que lleva concat y comprimir todos estos archivos es esencialmente el mismo en ambos escenarios.
Excepto cuando se utiliza también la opción sourceMap: true
en concat
(ver más abajo).
En mi computadora:
grunt default : 6.2s (just uglify)
grunt default:true : 6s (concat and uglify)
Vale la pena señalar que el main.min.js
resultante es el mismo en ambos casos.
Además, uglify
automáticamente se encarga de usar el separador adecuado al combinar los archivos.
El único caso en el que importa es cuando se agrega sourceMap: true
a las options
concat
.
Esto crea un archivo main.js.map
junto a main.js
, y da como resultado:
grunt default : 6.2s (just uglify)
grunt default:true : 13s (concat and uglify)
Pero si el sitio de producción solo carga la versión min
, esta opción es inútil.
Encontré una gran desventaja con el uso de concat
antes de uglify
.
Cuando se produce un error en uno de los archivos JS, el sourcemap
se vinculará al archivo main.js
concatenado y no al archivo original. Mientras que uglify
hace todo el trabajo, se vinculará al archivo original.
Actualizar:
Podemos agregar 2 opciones más para uglify
que vinculará el uglify
origen de uglify para concat
mapa de origen, manejando así la "desventaja" que mencioné anteriormente.
uglify: {
options: {
compress: true,
mangle: true,
sourceMap: true,
sourceMapIncludeSources: true,
sourceMapIn: ''<%= paths.dest.js %>.map'',
},
target: {
src: ''<%= paths.src.js %>'',
dest: ''<%= paths.dest.jsMin %>''
}
}
Pero parece muy innecesario.
Conclusión
Creo que es seguro concluir que podemos concat
de concat
para archivos JS si estamos usando uglify
, y usarlo para otros propósitos, cuando sea necesario.
En el ejemplo que menciona, que cito a continuación, los archivos primero se concatenan con concat
y luego se uglifican / minimizan con uglify
:
{
concat: {
''.tmp/concat/js/app.js'': [
''app/js/app.js'',
''app/js/controllers/thing-controller.js'',
''app/js/models/thing-model.js'',
''app/js/views/thing-view.js''
]
},
uglifyjs: {
''dist/js/app.js'': [''.tmp/concat/js/app.js'']
}
}
Lo mismo se podría lograr con:
{
uglifyjs: {
''dist/js/app.js'': [
''app/js/app.js'',
''app/js/controllers/thing-controller.js'',
''app/js/models/thing-model.js'',
''app/js/views/thing-view.js''
]
}
}
Por lo general, la clean
tareas se ejecutaría después de las tareas que escriben en una carpeta temporal (en este ejemplo concat
) y eliminan el contenido de esa carpeta. A algunas personas también les gusta ejecutar tareas clean
antes de tareas como la compass
, para eliminar cosas como sprites de imágenes con nombres aleatorios (que se generan cada vez que se ejecuta la tarea). Esto mantendría las ruedas girando incluso para los más paranoicos.
Todo esto es una cuestión de preferencia y flujo de trabajo, como lo es cuando se ejecuta jshint
. A algunas personas les gusta ejecutarlo antes de la compilación, otras prefieren ejecutarlo en archivos compilados.
Los proyectos complejos con una cantidad increíble de archivos JavaScript
, o con un número cada vez más amplio de colegas y colaboradores, pueden optar por concatenar archivos fuera de uglify
solo para mantener las cosas más legibles y uglify
mantener. Creo que este fue el razonamiento detrás de la elección del flujo de transformación de Yeoman
.
uglify
puede ser notoriamente lento dependiendo de la configuración del proyecto, por lo que puede haber una pequeña ganancia en concatenarla con concat
primero, pero eso debería confirmarse.
concat
también admite separadores, que uglify
no lo hace en lo que README.md
archivos README.md
.
concat: {
options: {
separator: '';'',
}
}