29

I've got a two-step compilation process for my web application. Firstly, I compile CoffeeScript files into JavaScript files [1]. Then the JavaScript files (both ones that come from CoffeeScript, and external ones, like produced from AngularJS templates by grunt-angular-templates) are compiled by Google Closure Compiler [2] into a single minimized file.

CoffeeScript ---[1]---> JavaScript --[2]--\
                                           \->
AngularJS templates --> JavaScript ----------> single minimized JS file
                                           /->
                    other JS files -------/

Both steps [1] and [2] produce source maps.

Is it possible to combine these source maps into a single source map that would allow me to debug CoffeeScript files from a web browser that runs the minimized JS file?

In other words: let say the source map [1] is represented by a function:

f(position in CoffeeScript) = position in JavaScript

and the source map [2] is represented by a function:

g(position in JavaScript) = position in minimized JS

I'd like to get a source map which is represented by a function composition:

h(position in CoffeeScript) = g(f(position in CoffeeScript)) = 
                            = position in minimized JS
liori
  • 40,917
  • 13
  • 78
  • 105

5 Answers5

21

Try sorcery - it's designed for exactly this purpose (I'm the author, I came here looking for info on related tools). As long as the .map files are in the correct location (or inlined as data URIs), you just run sorcery on the generated file and it will locate the intermediate sourcemaps and compose them.

Rich Harris
  • 28,091
  • 3
  • 84
  • 99
  • 1
    Hello Rich, could you please provide some example how to use your tool for example with gulp? Because it's not very obvious from your documentation on github how to do it. Thank you in advance. – VladosJS Nov 03 '16 at 09:57
  • @Rich Harris. Thank you for this addon. It works great! – aandis Jun 13 '18 at 06:42
3

As best I can tell from the source map specification (and other discussions), multilevel mapping has not yet been defined

https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#heading=h.e8hx254xu4sa

Source Maps Revision 3; Multi-level Mapping Notes

Someone may have developed some tools to address this, maybe in a Github repository. Of course you have both the tools to generate such maps, and browsers that can use them.

https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/ https://github.com/fitzgen/source-map

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Well, in my use case I don't really care about the intermediate file, it's just a by-product… anyway, your answer at least tells me that this idea is technically feasible with current implementation of source maps, and there's just no tool that performs exactly this operation. Thank you. – liori Feb 12 '14 at 13:28
  • Looks like `Grunt` can handle a 2 stage map, at least in the case of passing a single compiled `Coffeescript` through `uglify` - https://github.com/gruntjs/grunt-contrib-uglify – hpaulj Feb 12 '14 at 18:09
  • And via those links, Powerbuild: https://github.com/tarruda/powerbuild `minimal CommonJS browser bundler with aliasing, extensibility, and source maps` – hpaulj Feb 12 '14 at 18:15
3

Closure Compiler now implements --apply_input_source_maps (and --parse_inline_source_maps to boot). That should do exactly what you're trying to achieve here, no additional tooling required.

Martin Probst
  • 9,497
  • 6
  • 31
  • 33
  • 1
    No additional tooling required only if there are only two phases of code transformation. – liori Sep 20 '16 at 10:40
  • @liori yes, no tooling required for the setup described in this question. But generally, as long as all tools keep all sourcemaps inline, and all tools support reading inline source maps (I know not all do, but that seems like a reasonable goal), this Should All Work (tm). – Martin Probst Oct 12 '16 at 01:23
2

The combine-source-map package, a Mozilla [source-map] wrapper looks like a more popular alternative to [sorcery], as Rich Harris had recommended (2M vs. 32k downloads).

By the product page's own description, combine-source-map will:

Add source maps of multiple files, offset them and then combine them into one source map.

After evaluating merge-source-maps it looks promising, even though it only handles file system-based sources in source maps. It crashes when using inline sources (may be a limitation of the original code from closure compiler). With a few changes, it can be made to properly handle inline sources, as well.

0

The answer seems to be a little outdated. Try remapping, @babel/core use it for transformOptions inputSourceMap. You can see how babel use it here, it encapsule a function called 'mergeSourceMap'

D.H.Lolo
  • 53
  • 4