Klathmon / imagemin-webpack-plugin

Plugin to compress images with imagemin
MIT License
684 stars 53 forks source link

Can it work together with copy-webpack-plugin? #6

Closed colthreepv closed 8 years ago

colthreepv commented 8 years ago

It would be bliss if those plugins could work together, so to copy images and compress them.

Do you have any idea how to accomplish this?

Klathmon commented 8 years ago

It's possible, but it looks like it will require changes in copy-webpack-plugin.

My plugin works in the compilation phase of the compiler in webpack. Unfortunately it looks like the copy-webpack-plugin does all of it's work in the emit phase of the compiler (which happens after my plugin is done).

That being said, it looks like copy-webpack-plugin works by adding the files to the webpack assets array and lets webpack write them to the output directory. This means that if copy-webpack-plugin is modified to run in a phase before compilation (specifically the this-compilation event that I use here), then my plugin will automatically start optimizing any images it adds.

Now the docs for webpack plugins are awful, and it looks like the author of copy-webpack-plugin knows more about it than I do, so there is a good chance that his plugin is working on the correct event and mine needs to be modified to a later event like emit. (If you or anyone else knows the answer to this, please let me know!).

So the TL;DR to my rambling is:

It's possible, and it shouldn't be too much work, but it will require changes in one of our plugins, and i'm not sure which...

If you are adventurous and have some time to spend on this, you can try playing with the event that either plugin runs off of to see if you can get it working (specifically this line in my plugin, and this line in copy-webpack-plugin)

colthreepv commented 8 years ago

thanks for taking a look at the codebases, briefly after posting the issue I did as well and couldn't help but notice the discrepancy between webpack events...

I will try in the spare time to provide a solution, I'm no webpack expert either, and I know their documentation is one of worlds misteries 😭

My usecase was so simple that i ended up just using an npm script with imagemin-cli instead of copy-webpack and imagemin-wepbapack

Klathmon commented 8 years ago

Yeah, and sometimes that's the best idea. It also sounds like a perfect use case for something like gulp, and gulp and webpack work great together.

Still, I'd like to at least follow up on this to at the very least know if i'm running my plugin at the right point...

stimmins commented 8 years ago

I've been looking into this today and I believe I've been able to move to using the emit event, as you suggested.

Klathmon commented 8 years ago

Just to ping @colthreepv, the fix to have these 2 work together is merged in, and it'll be out in the next release by tonight.

Klathmon commented 8 years ago

cut as version 1.1.0

stevemao commented 7 years ago

@Klathmon Does the order matters when using with CopyWebpackPlugin? I'd add a tip in README on this :)

Klathmon commented 7 years ago

@stevemao I'm honestly not sure. I don't use CopyWebpackPlugin so I can't really test easily.

If you can confirm whether the order is important or not, i'd gladly add it to the README somewhere (or accept a PR if you want to add it yourself).

stevemao commented 7 years ago

@Klathmon https://github.com/Klathmon/imagemin-webpack-plugin/pull/20

assumptionsoup commented 7 years ago

I just tried this, and I noticed that order did matter. ImageminPlugin must come after CopyWebpackPlugin in the plugin definition:

Ex:

module.exports = {
  plugins: [
    new CopyWebpackPlugin(
      [
        {
          from: path.resolve(__dirname, ROOT, 'src/images/'),
          to: path.resolve(__dirname, ROOT, 'dist/images/')
        },
      ]),
      new ImageminPlugin({
        test: /\.(jpe?g|png|gif|svg)$/i,
        pngquant: {
          quality: '95-100'
        }
      })
    ]
};
Klathmon commented 7 years ago

@assumptionsoup Yeah @stevemao created a PR and added this to the README.md already!

assumptionsoup commented 7 years ago

Oh cool! I guess I missed it. :)

Giovancruz commented 3 years ago

I'm sorry for reliving the topic but I need help. I am using code similar to the one published in the readme and here, my images continue to be copied, but arent being optimized, no error occurs.

I joined on a project that uses webpack 4 but I believe that the best alternative to the way it is being used would be gulp. I'm also dont have expertise on webpack, but unfortunally I don't have the time to change that now either update to webpack 5. Here is the code:

module.exports = {
  plugins: [
    new CopyPlugin([{
      from: path.join(source, 'src/fonts'),
      to: './fonts',
    },
    {
      from: path.join(source, '/src/images'),
      to: './images',
    },
    ], {
      copyUnmodified: true
    }),
    new ImageminPlugin({
      disable: process.env.NODE_ENV !== 'production',
      test: /\.(jpe?g|png|gif|svg)$/i,
      plugins: [
        ["gifsicle", { optimizationLevel: 3, interlaced: true }],
        ["jpegtran", { quality: 100, progressive: true }],
        ["optipng", { optimizationLevel: 3, interlaced: true }],
        ["svgo", {
          plugins: [{
            removeViewBox: false,
            convertPathData: false,
            removeDimensions: true,
            removeStyleElement: true
          }]
        }],
      ],
    }),
  ]
};

I verified that in the copy plugin there is a transform method, but I am not able to fit something that returns the optimized buffer.

{
  from: path.join(source, '/src/images/**/*.png'),
  to: './images',
  transform(content, path) {
    if (process.env.NODE_ENV !== 'production') {
      return imageminOptipng({
        interlaced: true
      });
     //The "data" argument must be one of type string, TypedArray, or DataView. Received type function
    }
  },
}

Can anybody help me please?