Skip to content

Instantly share code, notes, and snippets.

@jakearchibald
Created February 28, 2020 10:07
Show Gist options
  • Save jakearchibald/ee75c204a5fead04672f3046d1fe27d3 to your computer and use it in GitHub Desktop.
Save jakearchibald/ee75c204a5fead04672f3046d1fe27d3 to your computer and use it in GitHub Desktop.
import { createHash } from 'crypto';
function removeAssetHash(fileName) {
const noHashFilename = fileName.replace(/-[a-f0-9]+(\.[^.]+)$/, '$1');
if (fileName === noHashFilename) {
console.warn(`Skipping ${fileName} - couldn't find hash in filename`);
}
return noHashFilename;
}
export default function importMapPlugin() {
let assetsToMap;
return {
name: 'import-map-plugin',
buildStart() {
assetsToMap = new Set();
},
resolveFileUrl({ fileName }) {
assetsToMap.add(fileName);
return `System.resolve('./${removeAssetHash(fileName)}')`;
},
generateBundle(outputOpts, bundle) {
const importMap = { imports: {} };
const assets = Object.values(bundle).filter(b =>
assetsToMap.has(b.fileName),
);
const chunks = Object.values(bundle).filter(b => b.type === 'chunk');
for (const asset of assets) {
const noHashFilename = removeAssetHash(asset.fileName);
importMap.imports['./' + noHashFilename] = './' + asset.fileName;
this.emitFile({
type: 'asset',
source: asset.source,
fileName: noHashFilename,
});
}
for (const chunk of chunks) {
const hash = createHash('md5');
hash.update(chunk.code);
const hashedFilename = chunk.fileName.replace(
/\.js$/,
`-${hash.digest('hex').slice(0, 8)}.js`,
);
importMap.imports['./' + chunk.fileName] = './' + hashedFilename;
this.emitFile({
type: 'asset',
source: chunk.code,
fileName: hashedFilename,
});
}
this.emitFile({
type: 'asset',
source: JSON.stringify(importMap),
fileName: 'import-map.json',
});
},
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment