gruntjs - 为什么建议先使用 concat,然后使用 uglify,而后者可以两者兼得?

标签 gruntjs uglifyjs grunt-contrib-concat

我不断看到建议将 JS 文件准备好用于生产,先 concat 然后 uglify。

例如here ,在 Yeoman 的繁重任务中。

By default the flow is: concat -> uglifyjs.

考虑到 UglifyJS 可以同时进行串联和缩小,为什么你会同时需要两者?

谢谢。

最佳答案

运行基本测试,看看执行 concatuglify 与仅执行 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源代码,复制了几次,分散到子文件夹中。比普通网站/应用程序通常拥有的内容要多得多。

事实证明,在这两种情况下,连接和压缩所有这些文件所需的时间基本上是相同的。
异常(exception),即在 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 旁边创建一个 main.js.map 文件,并导致:

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,我们可以放弃 concat 来使用 JS 文件,并在需要时将其用于其他目的。

关于gruntjs - 为什么建议先使用 concat,然后使用 uglify,而后者可以两者兼得?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22544649/

相关文章:

javascript - php文件中的uglifyjs javascript

webpack - 如何避免库与 UglifyJs 或 Terser Webpack 插件混淆?

html - Grunt concat html 和 js 有不同的分隔符?

javascript - Grunt 文件默认将 nonull 设置为 true

java - 如何使用 spring boot/maven 更改不同配置文件中index.html的位置?

javascript - 如何在 Gulp 中使用 Browserify 丑化输出?

node.js - Grunt 产生的进程没有捕获输出

javascript - Grunt 排除在构建期间连接一些文件

node.js - 使用 grunt 服务器,如何将所有请求重定向到根 url?

git - 当我将我的项目发布到 GitHub 时,我应该如何处理 Grunt 的 node_modules 目录?