Uglifyjs: Support multiple --in-source-map arguments

Created on 6 Mar 2013  路  29Comments  路  Source: mishoo/UglifyJS

When using UglifyJS2 to concatenate multiple JavaScript source files generated by compile-to-JS transpilers like CoffeeScript, since each JS file has its own source map file, it is critical to have UglifyJS2 supports multiple --in-source-map arguments so it can consolidate the source map files as it concatenates the JavaScript source files. Or did I miss anything obvious?

source-map

All 29 comments

yes, it's a great tool, but this is sorely missing.

+1

For those interested, I created a very simple utility called mapcat that consolidates source map files while concatenating js files. It's very primitive at the moment, but I can use it as the step before UglifyJS2. Feel free to expand it as you see fit.

Handling this through an external tool like mapcat seems totally reasonable.

Perhaps a good solution (at UglifyJS level) would be to scan the input files for the //@sourceMappingURL comment, and use that map if we can find it? What do you think? (it's somewhat tricky to implement, however).

That is indeed tricky. How about just allow people to specify multiple --in-source-map, like:

uglify --in-source-map module1.map --in-source-map module2.map

You could also allow regular JS - those hand-written and without associated map file - to be supplied as well:

uglify --in-source-map module1.map --in-source-map module2.map module3.js

(mapcat currently does not support this. otherwise it could be a used as a good preprocessor.)

+1 (or someone gets the coffeescript compiler to properly join multiple files and their source maps.)

Browserify took a bit different route (which I find quite compelling):

browserify('main.coffee').transform(coffeeify).bundle({debug: true})

builds a single file with main.coffee and all dependencies included. Source map is inlined at the end of result stream with base64 encoding. Works like a charm.

Could Uglify decode the source map and replace it with a multilevel source map? I'd love to do something like

browserify('main.coffee')
  .transform(coffeeify)
  .bundle({debug: true})
  .pipe(UglifyJS.transformStream({debug: true})
  .pipe(fs.createWriteStream('dist.js'));

..and have multilevel sourcemap inlined all the way.

Also was surprised to find out than uglifyjs supports joining multiple files generated by CoffeeScript, but cannot use sourceMappingURL included in every such file (instead of using --in-source-map).

@Inversion-des That's the plan. I'll do that.

I recently implemented some new features to the source-map library which should make it really easy to work with SourceMaps:

// Concatenating files including SourceMaps
new SourceNode(null, null, null, [
  SourceNode.fromStringWithSourceMap(contentFile1, sourceMapFile1),
  SourceNode.fromStringWithSourceMap(contentFile2, sourceMapFile2)
]).toStringWithSourceMap()
// => { code, map }
// Mutliple levels of SourceMaps (like coffee -> js -> min)
var aggregatedMap = SourceMapGenerator.fromSourceMap(sourceMapJsToMinJs);
aggregatedMap.applySourceMap(sourceMapCoffeeScriptToJs);
aggregatedMap.toString()

Even if uglifyjs wouldn't support --in-source-file, one can easily build a small tool which aggregates the SourceMaps.


@mishoo You can use this by just ignoring the inSourceMap while minimizing and apply all inSourceMaps after that process.

I've been doing this for a while with projmate, which is a cross between grunt and browserify. See coffee-backbone-sourcemap example. Basically, the project compiles all CoffeeScript _and_ JavaScript in a directory into a single CommonJS module (based on stitch) into a separate _build_ directory. Most transpliers generate the map in the same directory which is annoying.

+1

Hai Mihai, d膬-i bice !
This is a MUST have basic feature that needs to be supported when using with r.js

I'm really new to JavaScript, never mind source maps, so I just ran unwittingly into this. It'd be a big help if UglifyJS could read multiple source maps, as it would remove the mapcat step from my build pipeline. Using mapcat works fine, but involved an hour or two of searching around and plugging it in. It's a shame UglifyJS can read in multiple JS files but not multiple source maps, as it makes the feature a bit asymmetric.

+1 to automatic detection comment like //@sourceMappingURL

It solve the problem of joining multiple files with source map and without (https://github.com/pmuellr/cat-source-map) .
Several --in-source-map options look ugly. Also It can be a source of error related to the files order.

+1 for automatic detection for sourceMappingURL as this would simultaneously fix issue #151.

This could also deprecate the use of --in-source-map option resulting in a much cleaner and easy to use API.

+1

+1

I鈥檝e written source-map-resolve which can resolve a source map from a sourceMappingURL comment in a file. This is roughly how you could use it:

var resolveSourceMapSync = require("source-map-resolve").resolveSourceMapSync
var SourceMapConsumer    = require("source-map").SourceMapConsumer

// `files` is an array of {path: ..., content: ...} objects.
// `minifiedMap` is the source map UglifyJS has produced.
// `minifiedOutputPath` is the path to where `minifiedMap` will be written.

files.forEach(function(file) {
  var previousMap = resolveSourceMapSync(file.content, file.path, fs.readFileSync)
  if (previousMap) {
    minifiedMap.applySourceMap(
      new SourceMapConsumer(previousMap.map),
      file.path,
      path.relative(
        path.dirname(minifiedOutputPath),
        path.dirname(previousMap.sourcesRelativeTo)
      )
    )
  }
})

+1 to supporting //@sourceMappingURL

+1 to //@sourceMappingURL

+1 to read the original sources for //@sourceMappingURL

API support for multiple input sourcemaps is at https://github.com/mishoo/UglifyJS2/pull/706

Any progress with this? It's really useful if you ever need to debug a application in production, which most of us do.

Uglify is a volunteer effort. Likely no one is working on this. Pull requests welcome.

Hi thanks for merging this support in @alexlamsl. Are there some docs on how to use this?

It's a shame that the sourcemaps can't be automatically detected from the sourceMappingURL comment but anyway I'm trying this:

uglifyjs base.js button.js --source-map "filename='button.map.js'" --output all.js

But it doesn't work, and how do I add multiple (e.g. base.map.js too)? Thanks

It's a shame that the sourcemaps can't be automatically detected from the sourceMappingURL comment but anyway I'm trying this

FWIW I did this here: https://github.com/mishoo/UglifyJS2/pull/3220
and also here: https://github.com/terser-js/terser/pull/298

It's a shame that the sourcemaps can't be automatically detected from the sourceMappingURL comment but anyway I'm trying this

FWIW I did this here: #3220
and also here: terser-js/terser#298

Oh that's a shame they weren't merged, that is the API and logic that I would imagine would be the default solution out the box!

I suggest using that branch if it's a game changer for you. I used it in production at my last job, it worked well.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

neverfox picture neverfox  路  4Comments

gabmontes picture gabmontes  路  5Comments

alexlamsl picture alexlamsl  路  4Comments

PinkyJie picture PinkyJie  路  3Comments

GrosSacASac picture GrosSacASac  路  3Comments