symfony / webpack-encore

A simple but powerful API for processing & compiling assets built around Webpack
https://symfony.com/doc/current/frontend.html
MIT License
2.22k stars 197 forks source link

Enhancement: SVGO loader #349

Open Langmans opened 6 years ago

Langmans commented 6 years ago

Does encore have support for https://github.com/rpominov/svgo-loader? Has anyone added it manually?

Lyrkan commented 6 years ago

Hi @rubenvincenten,

Encore doesn't use that loader by default, SVG files are handled by either the file-loader or the url-loader based on your config:

https://github.com/symfony/webpack-encore/blob/63e15ce0be2e5735d13ac4bdfacf33c848d97610/lib/config-generator.js#L155-L173

The easiest way to add the svgo-loader is probably to disable the default images loader (using Encore.disableImagesLoader()) and create two new rules manually with Encore.addLoader() (one for your SVG files, the other one for the other types of images).

weaverryan commented 6 years ago

Hmm, it's a shame that Webpack doesn't allow you to (as far as I can see) add 2 rules that will match the same file. If it did, this could be accomplished by just adding a second loader, without needing to "remove" the existing loaders.

@Lyrkan's solution is correct, which is unfortunate, because you're really doing & removing a lot just to prepend this one loader.

I suppose we could add some way to prepend the image loaders? Though it might be getting kinda crazy:

Encore.prependImageLoader('svg', 'svgo-loader');

When detecting this, we would actually need to split our one loader into multiple (https://github.com/symfony/webpack-encore/blob/63e15ce0be2e5735d13ac4bdfacf33c848d97610/lib/config-generator.js#L170) - 1 for svg (with the prepended extra loader) and one for everything else. Not sure I love it :/

Lyrkan commented 6 years ago

@weaverryan I think you can add two rules that match a single file, I'm just not sure how it behaves when you do it... I stumbled upon this SO answer but it's starting to be a bit old and couldn't find something to back it up in Webpack's documentation. If that's still the case then a single call to addLoader() with only the svgo-loader may be enough...

Not sure about your solution either, but mainly because of the naming which could be a bit ambiguous based on how well you know Webpack (in that case you'd actually append it to the loaders chain... which is then applied in the reverse order)

Maybe the disableImageLoader could take an array of extensions that need to be disabled? For instance:

// Remove "svg" from the "test" part of the rule
Encore.disableImageLoader(['svg']);

// Remove "jpg" and "jpeg"
Encore.disableImageLoader(['jpg', 'jpeg']);
romantymoshyk commented 5 years ago

I was able to run SVGO with next code:

Encore.addRule({
        test: /\.svg$/,
        use: [
            {
                loader: 'file-loader',
                options: {
                    name: 'images/[name].[hash:8].[ext]',
                    publicPath: Encore.getWebpackConfig().publicPath
                }
            },
            {
                loader: 'svgo-loader',
                options: {
                    plugins: [
                        {removeTitle: true},
                        {convertColors: {shorthex: false}},
                        {convertPathData: false},
                        {inlineStyles: true}
                    ]
                }
            }
        ]
    });
fkaminski commented 5 years ago

I am very new to webpack and encore. Previously i am using pure npm scripts to optimize my SVG'S with svgo. So my Question:

When i try the above sample (or any other plugin like imagemin) with webpack encore the optimization process is carried out every time. Or am i wrong? How can i optimize the SVG's only once?

romantymoshyk commented 5 years ago

@fkaminski, it depends on webpack mode runned on, for prod mode for example webpack will optimize your svg's on each run, but in watch mode only on svg's changes. Also you may use cache-loader to avoid running svg optimization if images were not changed Independent runned mode. Also you may configure webpack to perform svg optimization only in prod mode. Generally, svg's optimization is recommended only if you have dependency on library which contains not optimized svgs, for example framework or font library which contain svg fonts/assets. If you don't have such dependencies there are no sens to run optimization on each webpack's run because you can store your own svg's already optimized.

fkaminski commented 5 years ago

Thanks, i found #567 and https://github.com/webpack/webpack/issues/2254 also - maybe this is an alternative way too ...