如何使用 Grunt 为 Uglified 文件生成源映射?

How do I generate sourcemaps for Uglified files using Grunt?

我有一个同时使用 Browserify 和 Uglify 的 Grunt 项目。这是它的核心部分:

browserify: {
  myapp: {
    options: {
      transform: ['babelify'],
      browserifyOptions: {
        debug: true
      },
    },
    src: 'src/index.js',
    dest: 'build/myapp.js'
  }
},

uglify: {
  options: {
    sourceMap: true,
    banner: bannerContent
  },
  target: {
    src: 'build/myapp.js',
    dest: 'build/myapp.min.js'
  }
},

它似乎生成了一个 myapp.min.js.map 文件,但它不再具有浏览器化之前存在的源映射中的原始源。

生成的源映射文件包含以下内容:

{
  "version":3,
  "sources":[
    "myapp.js"
  ],
  "names":[
    ...
    ...
    ...
  ],
  "mappings":".........",
  "file":"myapp.min.js"
}

我试过使用 uglifyify Browserify 转换,但生成的文件似乎不如 Uglify 任务小。

我也将所有依赖项更新到最新,但我无法解决这个问题。

grunt-contrib-uglify 有一个 sourceMapIn 选项,允许您指定来自早期编译的输入源映射文件的位置 - 在您的场景中是 browserify 任务。

然而,虽然在 browserify 任务中设置 browserifyOptions: { debug: true } 确实会在生成的 .js 文件(即 build/myapp.js 中)中生成内联源映射,但问题的症结在于问题是双重的:

  1. 我们没有可以配置后续 grunt-contrib-uglify 任务的 sourceMapIn 选项的外部源映射文件。

  2. grunt-browserify 不提供创建外部 .map 文件的功能,它仅内联创建它们(参见 here

要解决上述问题,请考虑在生成后利用 grunt-extract-sourcemapbuild/myapp.js(即从您的 browserify 任务生成的输出文件)中提取内联源映射.

Gruntfile.js

以下要点显示了您的 Gruntfile.js 应该如何配置:

module.exports = function (grunt) {

  grunt.initConfig({

      browserify: {
        myapp: {
          options: {
            transform: ['babelify'],
            browserifyOptions: {
              debug: true
            },
          },
          src: 'src/index.js',
          dest: 'build/myapp.js'
        }
      },

      extract_sourcemap: {
        myapp: {
          files: {
            'build': ['build/myapp.js']
          }
        }
      },

      uglify: {
        options: {
          sourceMap: true,
          sourceMapIn: 'build/myapp.js.map'
        },
        target: {
          src: 'build/myapp.js',
          dest: 'build/myapp.min.js'
        }
      }

  });

  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-extract-sourcemap');
  grunt.loadNpmTasks('grunt-contrib-uglify');

  // Note the order of the tasks in your task list is important.
  grunt.registerTask('default', ['browserify', 'extract_sourcemap', 'uglify']);
};

说明

  1. 首先调用 browserify 任务输出一个新文件(即 build/myapp.js),其中包含捆绑的 JavaScript 和 "inlined" 源地图信息。如果您在此阶段检查 build/myapp.js 的内容,它在末尾包含类似以下内容:

    //# sourceMappingURL=data:application/json;charset=utf-8;base64, ...
    
  2. 接下来调用 extract_sourcemap 任务。这实质上是从 build/myapp.js 中提取 "inlined" 源映射信息并将其写入名为 myapp.js.map 的新文件,该文件保存在 build 目录。

    build/myapp.js中原来的"inlined"源映射信息被新生成的源映射文件link替换,即myapp.js.map。如果您检查 build/myapp.js 的内容,您现在会在文件末尾注意到以下内容:

    //# sourceMappingURL=myapp.js.map
    
  3. 最后 uglify 任务被调用。请注意其 sourceMapIn 选项如何配置为读取 build/myapp.js.map,即我们在第 2 步生成的源映射文件。

    此任务会创建您想要的 build/myapp.min.js 文件,其中包含;你缩小的 JS,和一个 link 到一个新生成的源映射文件 build/myapp.min.js.map.

注意 最终生成的文件(即 build/myapp.min.js)现在可以正确映射回原始 src/index.js 文件和 index.js 本身可能有 import'ed 或 require()'d