Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Support manifest file #104

Open
evilebottnawi opened this issue Dec 20, 2016 · 19 comments

Comments

@evilebottnawi
Copy link
Member

commented Dec 20, 2016

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 😭

@SebastianS90

This comment has been minimized.

Copy link

commented Feb 19, 2017

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?

@Levdbas

This comment has been minimized.

Copy link

commented Nov 2, 2017

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.

danethurber/webpack-manifest-plugin#76

@IAMtheIAM

This comment has been minimized.

Copy link

commented Dec 5, 2017

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';
      }
   }),
@deguif

This comment has been minimized.

Copy link

commented Mar 3, 2018

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@4cb95ce

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.

@Levdbas

This comment has been minimized.

Copy link

commented Mar 5, 2018

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;
    },
  })
@jasonwilliams

This comment has been minimized.

Copy link

commented Apr 19, 2018

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

@evilebottnawi

This comment has been minimized.

Copy link
Member Author

commented Apr 19, 2018

@jasonwilliams Should be fix it danethurber/webpack-manifest-plugin#141 first and when i implement support webpack-manifest-plugin by default

@jasonwilliams

This comment has been minimized.

Copy link

commented Apr 19, 2018

@evilebottnawi for more info on the issue im having i created a ticket here:
danethurber/webpack-manifest-plugin#144

Looks like the same problem

@budarin

This comment has been minimized.

Copy link

commented Sep 24, 2018

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

@budarin

This comment has been minimized.

Copy link

commented Nov 21, 2018

any fixes here?

@evilebottnawi

This comment has been minimized.

Copy link
Member Author

commented Nov 23, 2018

@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

@budarin

This comment has been minimized.

Copy link

commented Nov 23, 2018

thanks for the reply

@kst83

This comment has been minimized.

Copy link

commented Mar 29, 2019

Would be great if you could release a version including this on npmjs.com

@chezhe

This comment has been minimized.

Copy link

commented Aug 28, 2019

@budarin Have you fix the problem —— key and value both hashed?

@chezhe

This comment has been minimized.

Copy link

commented Aug 28, 2019

@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?

@evilebottnawi

This comment has been minimized.

Copy link
Member Author

commented Aug 28, 2019

What is ManifestPlugin plugin? We need implement hook for this and plugins should use this hook

@chezhe

This comment has been minimized.

Copy link

commented Aug 29, 2019

What is ManifestPlugin plugin? We need implement hook for this and plugins should use this hook

Here is webpack-manifest-plugin

@chezhe

This comment has been minimized.

Copy link

commented Aug 29, 2019

What is ManifestPlugin plugin? We need implement hook for this and plugins should use this hook

#104 (comment)

This works for me, thanks for your reply.

@azdkj532

This comment has been minimized.

Copy link

commented Sep 12, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.