Open oupala opened 8 years ago
@ksmithut said:
Fingerprinting should definitely support sourcemaps, even if they don't. Most plugins that do support sourcemaps have some kind of input sourcemap option, which takes the input source map and generates a new sourcemap.
It appears that the way sourcemap is implemented by less and sass does not absolutely require that css file and its sourcemap have the same basename.
Looking at this page show that the sourcemap name is embedded in the css file:
This will create a .css.map source map file for each CSS file, and add a comment to the end of your CSS file with the location of the sourcemap: /# sourceMappingURL=index.css.map /. The devtools will use this source map to map locations in the CSS style sheet to locations in the original source.
As propagating the basename in the soucemap seems to be not mandatory, I let experts decide if this issue should be fixed or not.
:+1: — it'd be nice to have this.
if foo.css
is fingerprinted to foo-1a2b3c4d.css
, then the corresponding foo.css.map
should be fingerprinted to `foo-1a2b3c4d.css.map
as well. same with JavaScript.
the alternative is to just use embedded sourcemaps instead.
I updated locally to do this and optionally remove the originals
var crypto = require('crypto');
var multimatch = require('multimatch');
var path = require('path');
var sourceMapUrl = require('source-map-url');
var KEY = 'metalsmith';
module.exports = plugin;
function plugin(options) {
options = options || {};
return function (files, metalsmith, done) {
var metadata = metalsmith.metadata();
var remove = (options.remove || false);
Object.keys(files)
.filter(function (file) {
return multimatch(file, options.pattern).length > 0
})
.forEach(function (file) {
var hash = crypto.createHmac('md5', KEY).update(files[file].contents).digest('hex');
var ext = path.extname(file);
var fingerprint = [file.substring(0, file.lastIndexOf(ext)), '-', hash, ext].join('').replace(/\\/g, '/');
// update sourcemap
files[file].contents = updateSourceMapComment(file, files, fingerprint, remove);
// update filename
files[fingerprint] = files[file];
// delete original
if (remove) {
delete files[file];
}
// add metadata
metadata.fingerprint = (metadata.fingerprint || {});
metadata.fingerprint[file] = fingerprint;
});
return process.nextTick(done);
}
}
function updateSourceMapComment(filename, files, newFilename, remove) {
var newMapFilename = newFilename + '.map';
var contents = files[filename].contents.toString();
var currentMapFilename = filename + '.map';
// if there is a sourcemap in the contents then replace with fingerprint version and delete original
if (sourceMapUrl.existsIn(contents)) {
files[newMapFilename] = files[currentMapFilename];
if (remove) {
delete files[currentMapFilename];
}
return contents.replace(sourceMapUrl.regex, '/*# sourceMappingURL=' + newMapFilename + ' */');
}
return contents;
}
According to Source Map Revision 3 Proposal:
If a source file (css or js) is fingerprinted (which implies renamed), the link with the sourcemap (which is still old-named plus the
.map
extension) will be lost.Is there a way to relink the fingerprinted file and its sourcemap?
I can't see any obvious way to do this. Feel free to suggest a smart way to do this...