I am writing a plugin that needs to swap contents of a certain JSON file after all of the modules were bundled. I implemented it in 2 steps: loader replaces content with a placeholder, and the plugin replaces the placeholder.
the loader looks like this:
const loader = function(source) {
this.clearDependencies();
return JSON.stringify('REGENERATED_JSON');
};
the plugin looks roughly like this:
compilation.hooks.optimizeChunkAssets.tapAsync(PLUGIN_NAME, (chunks, callback) => {
chunks.forEach((chunk) => {
chunk.files.forEach((filePath) => {
const asset = compilation.assets[filePath];
const source = asset.source();
replacements.forEach((id) => {
const pattern = 'JSON.parse("\\"REGENERATED_JSON\\"")';
const index = source.indexOf(pattern);
if (index < 0) return;
const content = JSON.stringify(json_content, null, 2);
const updatedSource = new ReplaceSource(asset);
updatedSource.replace(index, index + pattern.length, content);
compilation.assets[filePath] = updatedSource;
});
});
});
callback();
});
This code has several issues:
- Fragile because it's tied to JSON.parse call. I wasn't able to trick webpack into treating file as javascript after it was imported as JSON.
- The content hash isn't being rebuilt, neither is the file size assessment, the JSON might be very large but Webpack wouldn't know.
Is there a way to solve these problems within webpack?