Make source maps refer to original files on remote

2019-07-05 20:27发布

问题:

Using Google Closure Compiler to minify a bunch of javascripts. Now I'd like to also add source maps to those to debug out in the wild.

Thing is, I want to keep the original (and preferrably also the map files) on a completely different place, like another server. I've been looking for a solution to this, and found out about the sourceRoot parameter. But it seems as it's not supported?

Also found this --source_map_location_mapping parameter, but no documentation whatsoever. Seems as it wants a pipe-delimited argument (filesystem-path|webserver-path). Tried a couple of different approaches to this, like local filename|remote url but without prevail. That just gives me No such file or directory and java.lang.ArrayIndexOutOfBoundsException.

Has anyone succeeded to place the minified/mapped source files on a remote machine?

Or does anyone know of any documentation for --source_map_location_mapping?

回答1:

The flag should be formatted like so:

--source_map_location_mapping=foo/|http://bar

The flag should be repeated if you need multiple locations:

--source_map_location_mapping=foo/|http://bar --source_map_location_mapping=xxx/|http://yyy

But what I expect that you are running into is that the "|" might be interpreted by your command shell. For example:

echo --source_map_location_mapping=foo/|http://bar
-bash: http://bar: No such file or directory

(The choice to use "|" was unfortunate). Make sure it is escaped appropriately. like:

--source_map_location_mapping="foo/|http://bar"

I submitted a pull request to report an error for badly formatted flag values:

https://github.com/google/closure-compiler/pull/620

which will at least you know that your flag value is incorrect (so you won't see the out of bounds exception).



回答2:

John is correct functionality-wise, but I think I can clear it up a bit (as this was super confusing for me to get working).

I suspect many people have the same issue as I:

  1. source map urls are generated relative to your current directory

  2. they don't necessarily match up to relative urls on your website/server

  3. Even if they did match up directly, the strangely-defined pseudo-spec found here means that Chrome/Firefox are going to try to load your paths relative to your sourcemap. i.e. the browser loads /assets/sourcemaps/main.map, sees assets/js/main.js, and loads /assets/sourcemap/assets/js/main.js (yay). (Or it might be relative to the original js file actually, I just happened to have them in the same directory).

Let's use the above example. Say we have assets/js/main.js in our sourcemap, and want to make sure that loads mywebsite.com/assets/js/main.js. To do this, you'd pass the option:

--source_map_location_mapping="assets|/assets"

Like John mentioned, quotes are important, and repeat the arg multiple times for multiple options. The prefixed / will let Firefox/Chrome know you want it relative to your website root. (If you're doing this in something like grunt-closure-tools you'll need to escape more:

config:{
    source_map_location_mapping:"\"assets|/assets\"",
}

This way, we can essentially map any given sourcemap path to any given website path. It's not really a perfect replacement for some sort of closure source root, but it does let you map each section of your sources individually to their own roots, so it's not that bad a compromise, and does give some additional flexibility (i.e. you could specify some cdn paths for some of your assets but not for other).

An additional thing you might find helpful, you can automatically add the sourceMappingURL via an output_wrapper. (Though, if you want the ability to debug in production, you should probably prefer some ability to make the server return X-Sourcemap: blah.js.map headers instead, inaccessible by the public)

--output_wrapper="(function(){%output%}).call(this); //# sourceMappingURL=/assets/js/my_main_file.js.map"


回答3:

Luckily Google Closure Compiler's source code is available publicly

https://gist.github.com/lydonchandra/b97b38e3ff56ba8e0ba5

REM --source_map_location_mapping is case SENSITIVE !
REM need extra escaped double quote   --source_map_location_mapping="\"C:/tools/closure/^|httpsa://bla/\"" as per http://stackoverflow.com/a/29542669
java -jar compiler.jar --compilation_level=SIMPLE_OPTIMIZATIONS --create_source_map=C:\tools\closure\latest\maplayer.js.map --output_wrapper "%output%//# sourceMappingURL=maplayer.js.map"  --js=C:\tools\closure\mapslayer.js --js_output_file=maplayer.min.js --source_map_location_mapping="\"C:/tools/closure/^|httpsa://bla/\""