Why?
In some projects, I use external library (example jquery) and for the implamentation of this, I use this plugin (just copy files from another directory to other). The plugin supports the use of hash, but do not know original file path and resulting file path (include hash and other stuff). There is no manifest file :sob:
Assuming you name your destination files [name].[hash:10].[ext], try out this plugin:
new StatsWriterPlugin({
fields: ['assets'],
filename: 'manifest.json',
transform(stats) {
const manifest = {};
stats.assets.map(asset => asset.name)
.sort()
.forEach((file) => {
manifest[file.replace(/\.[a-f0-9]{10}\./, '.')] = file;
// 10 is length of hash
});
return JSON.stringify(manifest, null, 2) + '\n';
}
})
Isn't that something you can work with?
The guys from webpack-manifest-plugin have included a hook in their latest RC release which other plugins can use to give before and after filenames and locations. Maybe this can be used to solve the hashing issue in a more convienient way? I am by no means capable of guessing if this can work but its merely a suggestion.
https://github.com/danethurber/webpack-manifest-plugin/pull/76
Here's a slightly modified regex that works with any length hash as long as it is inbetween two . characters, except the string .bundle. will be ignored
new StatsWriterPlugin({
fields : ['assetsByChunkName', 'assets'],
filename: 'webpack-manifest.json',
transform: function(stats) {
const manifest = {};
stats.assets.map(asset => asset.name)
.sort()
.forEach((file) => {
// matches anything between two dots `.` such as app.bundle.636876e2051c910a7ef8.js,
// app.chunk.636876e2051c910a7ef8.js, app.style.636876e2051c910a7ef8.css or
// app.636876e2051c910a7ef8.js, but don't match the `.bundle.`, `.chunk.`, or `.style.`
let regEx = /[^.]+\.(?=[^.]+$)/gmi;
let passTest = regEx.test(file);
let key = file.replace(regEx, '');
// remove any leading `/`
regEx = /^\//gmi;
key = key.replace(regEx, '');
// console.log(file, passTest, key);
manifest[key] = file;
});
return JSON.stringify(manifest, null, 2) + '\n';
}
}),
Hi,
For anyone wanting to use danethurber/webpack-manifest-plugin and be able to generate asset manifest which were copied with this plugin, here's my solution:
In webpack.config.js
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
...
module.exports = function (env) {
return {
...
output: {
path: path.resolve(__dirname, 'web/dist'),
publicPath: '/dist/',
},
plugins: [
new CopyPlugin([
{
context: path.join('/xxx/yyy', 'images'),
from: '**/*{.gif,.jpg,.jpeg,.png,.svg}',
to: 'images/[path][name].[ext]',
// to: 'production' === env.NODE_ENV ? 'images/[path][name].[hash].[ext]' : 'images/[path][name].[ext]',
toType: 'template',
},
]),
// Order matters, manifest plugin should be registered after copy plugin
new ManifestPlugin({
fileName: path.resolve(__dirname, 'var/assets/images/manifest.json'),
publicPath: '/dist/',
filter: (file) => file.name.startsWith('images/'),
/*map: (file) => {
if ('production' === env.NODE_ENV) {
// Remove hash in manifest key
file.name = file.name.replace(/(\.[a-f0-9]{32})(\..*)$/, '$2');
}
return file;
},*/
}),
],
};
}
__This will only work with version 2.x of danethurber/webpack-manifest-plugin currently in rc2__
See issue danethurber/webpack-manifest-plugin#75 and commit danethurber/webpack-manifest-plugin@4cb95ce41ec683078a6581949ec544f4a7d4a3d2
My example copy images from a /xxx/yyy/images to a web/dist/images folder and generate a manifest for images only in var/assets/images/manifest.json (Symfony 3 project). For using hash when copying the assets you will need a little adaption on manifest plugin, you can use the maphook to remove hash from filename (See my commented code).
I hope this will help people from this thread.
I do thank you a lot for the code that removes the hash (see under this text) from the file names. It works like a charm and simplifies my PHP function that includes the right asset a lot!
new ManifestPlugin({
map: (file) => {
if (process.env.NODE_ENV === 'production') {
// Remove hash in manifest key
file.name = file.name.replace(/(\.[a-f0-9]{32})(\..*)$/, '$2');
}
return file;
},
})
On --watch the manifest file (webpack-manifest-plugin) doesn't seem to update anything copy-webpack-plugin spits out.
This this being tracked anywhere? :(
It works fine on a fresh build, but only seems to fail on watch
@jasonwilliams Should be fix it https://github.com/danethurber/webpack-manifest-plugin/issues/141 first and when i implement support webpack-manifest-plugin by default
@evilebottnawi for more info on the issue im having i created a ticket here:
https://github.com/danethurber/webpack-manifest-plugin/issues/144
Looks like the same problem
I also have the problem when hasing filenames
Webpack: 4.19.1
copy-webpack-plugin: 4.5.2
plugins: [
new CopyWebpackPlugin([
{ from: './src/common/manifest.json', to: '[hash].[ext]' },
{ from: './src/common/favicon.ico', to: '[hash].[ext]' },
]),
new ManifestPlugin({
fileName: 'assets-manifest.json',
writeToFileEmit: true,
})]
here is assets-manifest.json
...
"83e7b321450bbcdc5013d2822838febc.json": "/83e7b321450bbcdc5013d2822838febc.json",
"4d263d3006aa8249f115a0318f48d3b3.ico": "/4d263d3006aa8249f115a0318f48d3b3.ico",
...
instead of having original names as the key - here is hashed name in both positions: key and value
any fixes here?
@budarin problem in implementation what we need event in manifest plugin (there are not one plugin) and event are difference, we can handle all plugins events. We should add hook on event https://github.com/danethurber/webpack-manifest-plugin/blob/master/lib/plugin.js#L191 and all copied files will be in manifest
thanks for the reply
Would be great if you could release a version including this on npmjs.com
@budarin Have you fix the problem —— key and value both hashed?
@evilebottnawi I met same problem with @budarin
webpack config
plugins: [
new CopyPlugin([{
from: 'public/src/img',
test: /\.(png|jpe?g|gif|svg)$/i,
to: 'img/[name].[md5:hash:hex:8].[ext]'
}, {
from: 'public/src/media',
to: 'media/'
}]),
extractCSS,
new ManifestPlugin({
fileName: 'manifest.json',
writeToFileEmit: true,
}),
]
And got manifest
"img/1-0-logo.e9833416.svg": "img/1-0-logo.e9833416.svg",
"img/2-0-logo.89e800b4.svg": "img/2-0-logo.89e800b4.svg",
"img/404.bfada369.png": "img/404.bfada369.png",
Any suggestion?
What is ManifestPlugin plugin? We need implement hook for this and plugins should use this hook
What is
ManifestPluginplugin? We need implement hook for this and plugins should use this hook
Here is webpack-manifest-plugin
What is
ManifestPluginplugin? We need implement hook for this and plugins should use this hook
https://github.com/webpack-contrib/copy-webpack-plugin/issues/104#issuecomment-370390225
This works for me, thanks for your reply.
I have another hack of making copy-webpack-plugin & webpack-assets-manifest works together.
static_file_mapping = {};
config = {
plugins: [
new CopyPlugin([{
from: {
glob: 'static/**/*.@(png|svg|jpg|gif|ico)',
dot: false,
noext: false,
},
to: '[contenthash].[ext]',
// flatten: true
transformPath(targetPath, absosutePath) {
relative_path = path.relative(
path.resolve(root_dir),
absosutePath)
static_file_mapping[relative_path] = targetPath;
return targetPath;
}
}]),
new ManifestPlugin({
assets: static_file_mapping,
})
]
}
The key point is to use transformPath for exposing mapping information to outside world. Then you can write this information to anywhere you want.
Most helpful comment
I do thank you a lot for the code that removes the hash (see under this text) from the file names. It works like a charm and simplifies my PHP function that includes the right asset a lot!