From 960754931236d3b03ac89b868d6424d6e1d21b3a Mon Sep 17 00:00:00 2001 From: Mac Siri Date: Wed, 8 Jul 2020 05:55:53 -0400 Subject: [PATCH] Use custom UglifierCompressor to enable source-maps (#9188) --- config/environments/production.rb | 2 +- ...ts_uglifier_with_source_maps_compressor.rb | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 config/initializers/sprockets_uglifier_with_source_maps_compressor.rb diff --git a/config/environments/production.rb b/config/environments/production.rb index 5927cb6e7..70541a747 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -31,7 +31,7 @@ Rails.application.configure do } # Compress JavaScripts and CSS. - config.assets.js_compressor = Uglifier.new(harmony: true) + config.assets.js_compressor = :uglify_with_source_maps # config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. diff --git a/config/initializers/sprockets_uglifier_with_source_maps_compressor.rb b/config/initializers/sprockets_uglifier_with_source_maps_compressor.rb new file mode 100644 index 000000000..0659168a8 --- /dev/null +++ b/config/initializers/sprockets_uglifier_with_source_maps_compressor.rb @@ -0,0 +1,49 @@ +require "sprockets/digest_utils" +require "sprockets/uglifier_compressor" + +module Sprockets + class UglifierWithSourceMapsCompressor < Sprockets::UglifierCompressor + def call(input) + data = input.fetch(:data) # Non-Uglified contents of the JS file + name = input.fetch(:name) # name of the to-be-compressed JS file. + + @uglifier ||= Autoload::Uglifier.new(@options.merge({ harmony: true })) + compressed_data, sourcemap_json = @uglifier.compile_with_map(input[:data]) + + # Update source map according to the version 3 spec: https://sourcemaps.info/spec.html + sourcemap = JSON.parse(sourcemap_json) + sourcemap["sources"] = [name + ".js"] + sourcemap["sourceRoot"] = ::Rails.application.config.assets.prefix + sourcemap["sourcesContent"] = [data] + sourcemap_json = sourcemap.to_json + + sourcemap_filename = File.join( + ::Rails.application.config.assets.prefix, + "#{name}-#{digest(sourcemap_json)}.js.map", + ) + sourcemap_path = File.join(::Rails.public_path, sourcemap_filename) + sourcemap_url = filename_to_url(sourcemap_filename) + + FileUtils.mkdir_p File.dirname(sourcemap_path) + File.open(sourcemap_path, "w") { |f| f.write sourcemap_json } + + # Add the source map URL to the compressed JS file. + compressed_data.concat "\n//# sourceMappingURL=#{sourcemap_url}\n" + end + + def filename_to_url(filename) + url_root = ::Rails.application.config.assets.source_maps_domain + File.join url_root.to_s, filename + end + + def digest(io) + Sprockets::DigestUtils.pack_hexdigest Sprockets::DigestUtils.digest(io) + end + end +end + +Sprockets.register_compressor( + "application/javascript", + :uglify_with_source_maps, + Sprockets::UglifierWithSourceMapsCompressor, +)