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

Closed
alexander-akait opened this issue Dec 20, 2016 · 20 comments
Closed

[Feature] Support manifest file #104

alexander-akait opened this issue Dec 20, 2016 · 20 comments

Comments

@alexander-akait
Copy link
Member

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
Copy link

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
Copy link

Levdbas 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.

shellscape/webpack-manifest-plugin#76

@IAMtheIAM
Copy link

IAMtheIAM 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
Copy link

deguif 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 shellscape/webpack-manifest-plugin#75 and commit shellscape/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
Copy link

Levdbas 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
Copy link

jasonwilliams 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

@alexander-akait
Copy link
Member Author

alexander-akait commented Apr 19, 2018

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

@jasonwilliams
Copy link

jasonwilliams commented Apr 19, 2018

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

Looks like the same problem

@budarin
Copy link

budarin 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
Copy link

budarin commented Nov 21, 2018

any fixes here?

@alexander-akait
Copy link
Member Author

@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
Copy link

budarin commented Nov 23, 2018

thanks for the reply

@ghost
Copy link

ghost commented Mar 29, 2019

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

@chezhe
Copy link

chezhe commented Aug 28, 2019

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

@chezhe
Copy link

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

@alexander-akait
Copy link
Member Author

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

@chezhe
Copy link

chezhe 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
Copy link

chezhe 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.

@squirrel532
Copy link

squirrel532 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.

@alexander-akait
Copy link
Member Author

Close in favor #538

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests