def digest!
      assets = asset_paths.map do |path|
        digest = Digest::MD5.new
        digest.update(File.read("#{base_dir}/#{path}"))

        digest_path = "#{path.sub_ext('')}-#{digest.hexdigest}#{File.extname(path)}"

        FileUtils.cp("#{base_dir}/#{path}", "#{base_dir}/#{digest_path}")

        [path, digest_path]
      end

      File.open(manifest_path, "w") do |manifest|
        manifest.write(assets.to_h.to_json)
      end

      update_cache!
    end
def digest!
      assets = asset_paths.map do |path|
        digest = Digest::MD5.new
        digest.update(File.read("#{base_dir}/#{path}"))

        digest_path = "#{path.sub_ext('')}-#{digest.hexdigest}#{File.extname(path)}"

        FileUtils.cp("#{base_dir}/#{path}", "#{base_dir}/#{digest_path}")

        [path, digest_path]
      end

      File.open(manifest_path, "w") do |manifest|
        manifest.write(assets.to_h.to_json)
      end

      update_cache!
    end
The #digest! method will run through all of the compiled assets and
 create a copy of each asset with a digest fingerprint. This fingerprint
 will change whenever the file contents change. This allows us to use HTTP
 headers to cache these assets as we will be able to reliably know when
 they change.

 These fingerprinted files are copies of the original. The originals are
 not removed and still available should the need arise to serve a
 non-fingerprinted asset.

 Example manifest:
 {
   app.js => app-76c6ee161ba431e823301567b175acda.js,
   images/logo.png => images/logo-869269cdf1773ff0dec91bafb37310ea.png,
 }

 Resulting File Structure:
 - /
   - app.js
   - app-76c6ee161ba431e823301567b175acda.js
   - images/
     - logo.png
     - logo-869269cdf1773ff0dec91bafb37310ea.png