为什么build议使用concat,然后uglify时,后者可以做到这一点?
我不断看到build立JS文件准备生产的build议是concat然后uglify。
例如在这里 ,在Yeoman的咕噜声的任务。
默认情况下,stream程是:concat – > uglifyjs。
考虑到UglifyJS可以同时进行连接和缩小,为什么你会同时需要两个?
谢谢。
运行一个基本的testing,看看执行concat
和uglify
之间是否存在性能差异,而不仅仅是uglify
。
的package.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'); }); };
在src
,我已经放了一堆JS文件,包括jQuery的未压缩源文件,多次拷贝,分散到子文件夹中。 比普通的网站/应用通常要多得多。
结果表明,在这两种情况下,连接和压缩所有这些文件的时间基本相同。
除了在concat
上使用sourceMap: true
选项(见下文)。
在我的电脑上:
grunt default : 6.2s (just uglify) grunt default:true : 6s (concat and uglify)
值得注意的是,在这两种情况下产生的main.min.js
是相同的。
此外, uglify
在组合文件时会自动使用正确的分隔符。
唯一的情况是,添加sourceMap: true
到concat
options
。
这会在main.js.map
旁边创build一个main.js
文件,结果如下:
grunt default : 6.2s (just uglify) grunt default:true : 13s (concat and uglify)
但是,如果生产站点仅加载min
版本,则此选项无用。
在uglify
之前,我确实发现了使用concat
一个主要缺点 。
当其中一个JS文件发生错误时, sourcemap
将链接到连接的main.js
文件,而不是原始文件。 而当uglify
完成整个工作时,它会链接到原始文件。
更新:
我们可以给uglify添加两个选项,将uglify源代码映射到concat
源代码映射,从而处理上面提到的“缺点”。
uglify: { options: { compress: true, mangle: true, sourceMap: true, sourceMapIncludeSources: true, sourceMapIn: '<%= paths.dest.js %>.map', }, target: { src: '<%= paths.src.js %>', dest: '<%= paths.dest.jsMin %>' } }
但是这看起来非常不必要。
结论
我认为可以断定,如果我们使用uglify
,我们可以对JS文件进行concat
,并在需要时将其用于其他目的。
在你提到的例子中,我在下面引用,文件首先与concat
连接,然后通过uglify ugl /
{ 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'] } }
以下情况也可以实现:
{ 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' ] } }
通常,任务clean
将在写入临时文件夹的任务(在本例中为concat
)之后运行,并删除该文件夹中的任何内容。 有些人也喜欢在像compass
这样的任务之前运行clean
,删除像随机命名的图像精灵(这是每次运行任务时新生成的)。 这将保持车轮转动,即使是最偏执狂。
这与所有运行jshint
和工作stream程jshint
。 有些人喜欢在编译之前运行它,有些人则喜欢在编译的文件上运行它。
具有令人难以置信的JavaScript
文件量的复杂项目(或者越来越多的同行和贡献者)可能会select在uglify
之外连接文件,以保持可读性和可维护性。 我认为这是Yeoman
select转型stream程的推理。
根据项目的configuration, uglify
可能会非常慢,所以可能会有一些小小的优势,首先将它与concat
连接起来,但是这将会得到证实。
concat
也支持分隔符, README.md
与README.md
文件README.md
。
concat: { options: { separator: ';', } }