When using: copy-webpack-plugin
And specifying to:
as: 'images/[name].[contenthash][ext]'
How do you reference these files in your templates without using
html-webpack-plugin
or handlebars-loader
?
I have solved this with the following solution:
/**
* Create a new plugin class.
*/
const StoreAssetsInfoKeysPlugin = class StoreAssetsInfoKeysPlugin {
/**
* Define `apply` as its prototype method.
* @param hooks
*/
apply({ hooks }) {
/**
* Using the 'afterCompile' hook:
* Use the 'assetsInfo' Map which contains the output of all asset paths,
* construct an array containing all these paths,
* then write an 'assets.json' file somewhere in your project.
*/
hooks.afterCompile.tapAsync('StoreAssetsInfoKeysPlugin', ({ assetsInfo }, callback) => {
fs.writeFileSync('/path/to/assets.json', JSON
.stringify(Array
.from(assetsInfo.entries())
.map(([key]) => `/assets/${key}`)));
callback();
});
}
};
/**
* The Webpack configuration for this
* example looks like this.
*/
export default {
plugins: [
new StoreAssetsInfoKeysPlugin(),
new CopyPlugin({
patterns: [{
from: '/path/to/images/*',
to: 'images/[name].[contenthash][ext]',
}],
}),
],
};
/**
* Create a helper function which will find the
* correct path from the 'assets.json'
*/
export const getAssetPath = function getAssetPath(directory, filename, ext) {
return JSON
.parse(fs.readFileSync('/path/to/assets.json'))
.find((value) => value
.match(`^.*?\\b${directory}\\b.*?\\b${filename}\\b.*?\\.${ext}\\b.*?$`));
};
/**
* Then use the helper function within your
* server-side templating engine:
*/
getAssetPath('images', 'my-image', 'svg');
Is this a suitable solution?
This was my first solution to achieve obtaining the file names with a [contenthash]
substitution in server-side templates.
I'm new to Webpack so any thoughts on this approach would be appreciated.
I try to define the goal in detail:
source files
of scripts, styles, images, and other assetsoutput filenames
containingcontenthash
Is the goal correct?
If yes, then you can use one powerful "html-bundler-webpack-plugin" without
html-webpack-plugin
,handlebars-loader
,copy-webpack-plugin
.For example, there is the file structure of the example:
There is source template file
src/views/index.hbs
(or other HTML file):The webpack.config.js:
If you will keep original template content and only replace source asset files with their hashed output filenames, then disable the rendering using the
preprocessor: false
plugin option.The processed (not rendered to html) template will be looks like:
If you will render any template into HTML, you can use one of supported templating engines "out of the box": Eta, EJS, Handlebars, Nunjucks, LiquidJS.
The config of the plugin to render handlebars template to HTML:
The rendered HTML: