我一直看到建议让JS文件准备好生产,然后uglify。
例如here,关于Yeoman的笨拙任务。
默认情况下,流程为:concat - > uglifyjs。
考虑到UglifyJS可以同时进行连接和缩小,为什么你需要同时进行这两种操作?
感谢。
答案 0 :(得分:48)
运行基本测试,以查看执行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源)复制了几次,并传播到子文件夹中。远远超过普通网站/应用程序通常拥有的内容。
在两种情况下,连接和压缩所有这些文件所花费的时间基本相同
在<{1}}上使用sourceMap: true
选项时除外(见下文)。
在我的电脑上:
concat
值得注意的是,两种情况下得到的grunt default : 6.2s (just uglify)
grunt default:true : 6s (concat and uglify)
都相同
此外,main.min.js
在组合文件时会自动使用正确的分隔符。
唯一重要的是将uglify
添加到sourceMap: true
concat
。
这会在options
旁边创建一个main.js.map
文件,结果为:
main.js
但是,如果生产站点仅加载grunt default : 6.2s (just uglify)
grunt default:true : 13s (concat and uglify)
版本,则此选项无效。
我在min
之前使用concat
确实发现了一个主要的劣势。
当其中一个JS文件发生错误时,uglify
将链接到连接的sourcemap
文件,而不是原始文件。当main.js
执行整个工作时,将链接到原始文件。
<强>更新强>
我们可以向uglify
添加另外两个选项,将uglify
源地图链接到uglify
源地图,从而处理&#34;劣势&#34;我上面提到过。
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 %>'
}
}
,我们可以放弃concat
获取JS文件,并在需要时将其用于其他目的。
答案 1 :(得分:27)
在您提及的示例中,我在下面引用的文件首先与concat
连接,然后由uglify
进行uglified / minified:
{
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
)的任务之后运行,并删除该文件夹中的任何内容。有些人还希望在clean
之类的任务之前运行compass
,以删除随机命名的图像精灵(每次运行任务时新生成的)。即使对于最偏执的人来说,这也会使轮子转动。
这完全取决于首选项和工作流程,以及何时运行jshint
。有些人喜欢在编译之前运行它,有些人喜欢在编译文件上运行它。
包含大量JavaScript
文件的复杂项目 - 或者拥有越来越多的同行&amp;贡献者可能会选择在uglify
之外连接文件,以使事情更具可读性和可维护性。我认为这是Yeoman
选择转换流程背后的原因。
uglify
可能是出了名的慢,因此首先将它与concat
连接可能会有一些小的好处 - 但这必须得到确认。
concat
还支持分隔符,uglify
与README.md
文件无关。
concat: {
options: {
separator: ';',
}
}