Add source map for sprockets
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
//= link_tree ../images
|
//= link_tree ../images
|
||||||
//= link_directory ../javascripts .js
|
//= link_directory ../javascripts .js
|
||||||
|
//= link_directory ../javascripts .js.map
|
||||||
//= link_directory ../stylesheets .css
|
//= link_directory ../stylesheets .css
|
||||||
|
//= link_directory ../stylesheets .css.map
|
||||||
|
87
lib/tasks/sourcemap.rake
Normal file
87
lib/tasks/sourcemap.rake
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Adapted from https://github.com/rails/sprockets/issues/502#issuecomment-1030634236
|
||||||
|
|
||||||
|
SOURCE_EXTENSIONS = %w[.css .js].freeze
|
||||||
|
|
||||||
|
namespace :assets do
|
||||||
|
def append_sourcemap
|
||||||
|
manifest_path = Dir[Rails.public_path.join('assets/.sprockets-manifest-*.json').to_s].max {|a, b| File.ctime(a) <=> File.ctime(b) }
|
||||||
|
return unless manifest_path
|
||||||
|
|
||||||
|
manifest_json = JSON.parse(File.read(manifest_path))
|
||||||
|
assets = manifest_json['assets']
|
||||||
|
manifest = manifest_json['files']
|
||||||
|
|
||||||
|
assets.each do |name, digested|
|
||||||
|
ext = File.extname(name)
|
||||||
|
next unless SOURCE_EXTENSIONS.include? ext
|
||||||
|
|
||||||
|
# Get the source map file from the manifest
|
||||||
|
map_digested = assets["#{name}.map"]
|
||||||
|
next unless map_digested
|
||||||
|
|
||||||
|
# Parse the source map file
|
||||||
|
source_map = JSON.parse(File.read(Rails.public_path.join('assets', map_digested).to_s))
|
||||||
|
|
||||||
|
# Replace the source map file name with the digested one
|
||||||
|
if source_map['sections'].present?
|
||||||
|
source_map['sections'].map! do |section|
|
||||||
|
section['map']['sources'].map! {|source| assets[source] || source }
|
||||||
|
section
|
||||||
|
end
|
||||||
|
elsif source_map['sources'].present?
|
||||||
|
source_map['sources'].map! {|source| assets[source] || source }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Write the source map file
|
||||||
|
asset_source = Rails.public_path.join('assets', map_digested).to_s
|
||||||
|
write_asset(asset_source, source_map.to_json, manifest)
|
||||||
|
|
||||||
|
# Construct the source map link
|
||||||
|
file = Rails.root.join("public/assets/#{digested}")
|
||||||
|
mapping_string = "sourceMappingURL=#{map_digested}"
|
||||||
|
|
||||||
|
mapping_string = case ext
|
||||||
|
when '.css' then "/*# #{mapping_string} */"
|
||||||
|
when '.js' then "//# #{mapping_string}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Read the source map file and append the source map link
|
||||||
|
write_asset(file, "#{file.read}\n#{mapping_string}", manifest)
|
||||||
|
end
|
||||||
|
|
||||||
|
File.write(manifest_path, manifest_json.to_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_asset(filename, content, manifest)
|
||||||
|
File.write(filename, content)
|
||||||
|
mtime = Sprockets::PathUtils.stat(filename)&.mtime
|
||||||
|
compress_asset(filename, content, mtime)
|
||||||
|
manifest[File.basename(filename)].merge!(changed_manifest(content, mtime))
|
||||||
|
end
|
||||||
|
|
||||||
|
def compress_asset(source_filename, content, mtime)
|
||||||
|
target = "#{source_filename}.gz"
|
||||||
|
|
||||||
|
File.open(target, 'wb') do |file|
|
||||||
|
Sprockets::Utils::Gzip::ZlibArchiver.call(file, content, mtime)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def changed_manifest(content, mtime)
|
||||||
|
digest = Sprockets::DigestUtils.digest(content)
|
||||||
|
hexdigest = Sprockets::DigestUtils.pack_hexdigest(digest)
|
||||||
|
|
||||||
|
{
|
||||||
|
'mtime' => mtime,
|
||||||
|
'size' => content.bytesize,
|
||||||
|
'digest' => hexdigest,
|
||||||
|
'integrity' => Sprockets::DigestUtils.hexdigest_integrity_uri(hexdigest),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
task precompile: :environment do
|
||||||
|
append_sourcemap
|
||||||
|
end
|
||||||
|
end
|
Reference in New Issue
Block a user