@lipemat/js-boilerplate
Version:
Dependencies and scripts for a no config JavaScript app
75 lines (67 loc) • 2.31 kB
text/typescript
import crypto from 'node:crypto';
import webpack, {type Compiler, type WebpackPluginInstance} from 'webpack';
import type {AssetsStorage, WebpackAssetsManifest} from 'webpack-assets-manifest';
/**
* Webpack plugin for injecting the content hash into
* the manifest.json created by the `webpack-assets-manifest` plugin.
*/
class WebpackAssetsHash implements WebpackPluginInstance {
private readonly manifest: WebpackAssetsManifest;
private readonly assets: { [ key: string ]: string } = {};
/**
* Pass the same constructed plugin provide to Webpack via
* the `webpack.dist` script.
*/
constructor( manifest: WebpackAssetsManifest ) {
this.manifest = manifest;
}
/**
* WebPack plugin entrypoint.
*
* @link https://webpack.js.org/contribute/writing-a-plugin/
*/
apply( compiler: Compiler ) {
this.manifest.hooks.transform.tap( 'WebpackAssetsHash', this.addHashToManifest.bind( this ) );
compiler.hooks.thisCompilation.tap( 'WebpackAssetsHash', compilation => {
compilation.hooks.processAssets.tap(
{
name: 'WebpackAssetsHash',
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ANALYSE,
},
this.storeContentHash.bind( this, compilation ),
);
} );
}
/**
* Store the content hash of each asset in this class, so we
* can inject it into the manifest.json file.
*
* Hash matches Webpack [contenthash].
*/
storeContentHash( compilation: webpack.Compilation ) {
for ( const asset of compilation.getAssets() ) {
this.assets[ asset.name ] = crypto.createHash( 'md5' )
.update( asset.source.source() )
.digest( 'hex' )
.substring( 0, 20 );
}
}
/**
* Inject the `hash` of the content into the manifest.json
* file generated by webpack-assets-manifest.
*
* @param {Object} assets
*/
addHashToManifest( assets: AssetsStorage ): AssetsStorage {
Object.keys( assets ).forEach( ( item: string ): void => {
if ( item in this.assets && this.assets[ item ] !== '' ) {
assets[ item ].hash = this.assets[ item ];
} else if ( assets[ item ].src in this.assets && this.assets[ assets[ item ].src ] !== '' ) {
// If the content hash was added to the asset name before storing.
assets[ item ].hash = this.assets[ assets[ item ].src ];
}
} );
return assets;
}
}
export default WebpackAssetsHash;