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

Images not optimized when inlined with url-loader #22

Closed
Bram-Zijp opened this issue Feb 9, 2017 · 6 comments
Closed

Images not optimized when inlined with url-loader #22

Bram-Zijp opened this issue Feb 9, 2017 · 6 comments

Comments

@Bram-Zijp
Copy link

Bram-Zijp commented Feb 9, 2017

When images get inlined by url loader they do not get minimized. With the image-webpack-loader they do get minified inline. Should have it inlined under 10KB atleast
Stats:
original: 37KB
not inline with imagemin-webpack-plugin: 5.7KB
inline with imagemin-webpack-plugin and url-loader: 37KB
inline with url-loader + image-webpack-loader: 6.4KB

@Klathmon Klathmon added the Bug label Feb 9, 2017
@Klathmon Klathmon self-assigned this Feb 9, 2017
@Klathmon
Copy link
Owner

Klathmon commented Feb 9, 2017

I didn't even think about inlined images!

I'll take a look at this. It should be fairly easy, but it's going to require some special handling.

Would you be able to point me to a repo that uses both this plugin and url-loader in this way that I can test on?

It's no big deal if you can't, but it would speed things up a bit.

@Bram-Zijp
Copy link
Author

I don't but this can be added to one of your own builds:


const ImageminPlugin = require('imagemin-webpack-plugin').default
const imageminMozjpeg = require('imagemin-mozjpeg')

new ImageminPlugin({
    test: /\.(jpe?g|png|gif|svg)$/i,
    optipng: {
        optimizationLevel: 7,
    },
    pngquant: {
        quality: '65-90',
        speed: 4,
    },
    gifsicle: {
        optimizationLevel: 3,
    },
    svgo: {
        plugins: [{
            removeViewBox: false,
            removeEmptyAttrs: true,
        }],
    },
    jpegtran: {
        progressive: true,
    },
    plugins: [
        imageminMozjpeg({
            quality: 65,
            progressive: true,
        }),
    ],
}),

{
    test: /\.(gif|png|jpe?g|svg)$/i,
    loader: 'url-loader',
    query: {
        limit: 50000,
        publicPath: '../',
        name: 'dist/images/bundle.[name].[hash:7].[ext]',
    },
},

@Klathmon
Copy link
Owner

Klathmon commented Feb 12, 2017

Ugh, this is gonna be a lot harder than it looked.

url-loader doesn't add anything to the assets array when it inlines an image. So they never even reach this plugin to have me test or anything to them.

I'm still looking into if there are any options here, but it's not looking good...

Just kind of "thinking out loud here":

  1. I might be able to hook to another even and grab these images before url-loader gets them, but that would really screw up things for other people which need this to run later in the pipeline (like when used with copy-webpack-plugin). So I'd probably have to hook into multiple events, and make sure I tag any "already optimized" images as such, then don't optimize them again if they show up on the later event. This would work with things like copy-webpack-plugin and would allow me to maybe grab the images before url-loader gets ahold of them.

  2. I can see if I can make a change to image-webpack-loader to give it a similar option to not imagemin any images above a specific size, then you could use both this plugin, and image-webpack-loader both for different images. It's messy, it requires more work on the person who is adding these plugins/loaders to their project, but it might be the best technical solution.

  3. I can see if there is some easy way to "extract" any inlined images from other assets, have imagemin work on them, then plug them back into the other asset in their optimized form. While the thought of this makes my skin crawl, if it's possible to implement consistently and without breaking all kinds of other stuff (like mucking with random base64 strings in the source), it would be ideal.

Let me know if you have any thoughts on the above options. I'm going to look into url-loader's code and see if there is anything there that can help. I'm loving option 1 the most, if it would work.

@Klathmon
Copy link
Owner

Okay, after looking into a few things, I think i've got an idea here.

I might be able to add my own "loader" to the pipeline using the normal-module-factory event, use that loader to optimize images before url-loader gets to them, and hopefully mark the assets I optimize so that when I run on the emit event I don't double-optimize assets which were hit by the loader.

I'm not sure if im abusing the hell out of the webpack pipeline here or not, but either way I'm gonna walk away from this for a while and think about it and play with some stuff.

Sorry, but don't expect this to be added today.

@sky0014
Copy link

sky0014 commented Aug 7, 2017

Have that done? I met the same problem. 😄

@Klathmon Klathmon added Enhancement and removed Bug labels Sep 1, 2017
@Klathmon
Copy link
Owner

Klathmon commented Sep 1, 2017

I'm going to be giving up on this for the forseeable future.

I'll leave the issue open, and if anyone comes along that is able to implement something to help solve this i'd be more than happy to work with them, but I just don't have the time to rewrite such a large part of this plugin to do a multi-pass optimization like that.

I recently added the option to optimize images only over a specific size, so as a "hacky" fix you can set this plugin to only apply to images over a given size, then use image-webpack-loader inline to minify those images specifically.

It's not ideal, but I just won't be able to realistically implement this correctly any time soon.

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

3 participants