danielstgt / laravel-mix-svg-vue

A Laravel Mix extension to inline SVG files with Vue.js and automatically optimize them with SVGO
MIT License
38 stars 9 forks source link

Issues with Laravel Mix 6.0.20 and above? #8

Closed HassanZahirnia closed 3 years ago

HassanZahirnia commented 3 years ago

Hey, After updating to Mix 6.0.20 I keep getting errors while the library is trying to process svg files :

Module build failed (from ./node_modules/img-loader/index.js): TypeError: Invalid host defined options at Object.module.exports (...\node_modules\img-loader\index.js:14:3)

It works fine when I revert back to Mix 6.0.19 Any ideas ? Thanks in advance!

danielstgt commented 3 years ago

Could you share your webpack.mix.js file?

Are you importing/using any other libraries or plugins in e.g. your app.js that use the img-loader plugin behind the scenes?

I wasn't able to recreate your issue, maybe you could try the following things:

besrabasant commented 3 years ago

I am facing the same issue.

HassanZahirnia commented 3 years ago

@danielstgt

  1. I just updated to latest Mix (6.0.25), still not working :(
  2. Tried npm ls img-loader to find out which packages uses img-loader, here is the result:
    +-- laravel-mix-svg-vue@0.3.3
    | `-- img-loader@3.0.2
    `-- laravel-mix@6.0.25
    `-- img-loader@4.0.0
  3. I've tried removing node_modules and doing a fresh install, doesn't work.
  4. One thing I don't understand about this library is why does it try to enforce the installation of svg-vue3 when I'm not even using vue 3 ? Whenever I try to run any Mix commands, it detects that svg-vue3 needs to be installed and does it automatically. And it's annoying cause it causes a conflict issue and then I have to use --legacy-peer-deps everytime I use a npm command. Here is the output of npm ls svg-vue3 :
    +-- laravel-mix-svg-vue@0.3.3
    | `-- svg-vue3@0.1.4 deduped
    `-- svg-vue3@0.1.4
  5. And here is my webpack.mix.js :
const mix = require('laravel-mix');

var webpack = require('webpack');
var path = require('path');

var BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
    .BundleAnalyzerPlugin;

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

require('laravel-mix-svg-vue');

mix.disableNotifications();

mix.alias({
    '@': path.join(__dirname, 'resources/js')
});

mix.webpackConfig({
    output: {
        chunkFilename: 'js/[name].js?id=[chunkhash]'
    },
    module: {
        rules: [
            {
                test: /\.(jpe?g|png|gif)$/i,
                type: 'asset'
            }
        ]
    },
    plugins: [
        new CopyWebpackPlugin({
            patterns: [
                {
                    from: 'resources/images',
                    to: 'images'
                },
                {
                    from: 'resources/videos',
                    to: 'videos'
                }
            ]
        }),
        new ImageMinimizerPlugin({
            minimizerOptions: {
                plugins: [
                    ['gifsicle', { interlaced: true }],
                    ['mozjpeg', {}],
                    ['pngquant', {}]
                ]
            }
        })
    ]
});
mix.js('resources/js/app.js', 'public/js')
    .vue({
        version: 2,
        globalStyles: {
            stylus: [
                './resources/stylus/rupture.styl',
            ]
        }
    })
    .svgVue()
    .sass('resources/sass/bulma.sass', 'public/css')
    .css('resources/css/vendor.css', 'public/css')
    .postCss('resources/css/tailwind.css', 'public/css', [require('tailwindcss')])
    .extract();

if (mix.inProduction()) {
    mix.version();
} else {
    mix.sourceMaps();
}
besrabasant commented 3 years ago

Ok.. I pinpoint the issue now... Laravel Mix v6 ships with webpack version 5 and this package depends on img-loader package which does support webpack 5. Please take a look at the issue here.

HassanZahirnia commented 3 years ago

Ok.. I pinpoint the issue now... Laravel Mix v6 ships with webpack version 5 and this package depends on img-loader package which does support webpack 5. Please take a look at the issue here.

You mean img-loader does not support webpack 5, right ? So we basically can conclude that we cannot use this package anymore until img-loader supports webpack 5 ? 😢

besrabasant commented 3 years ago

Yes and yes @xperator

HassanZahirnia commented 3 years ago

Yes and yes @xperator

Let me know if you have an alternative to this package. Because both this and img-loader package are slow at development and Mix is going fast so I can't hold back and stay behind at version 6.0.19

HassanZahirnia commented 3 years ago

I was so frustrated with the situation that I decided to do some modifications on the main script and somehow it turned out well and now it's working with Laravel 6.0.25 and I'm happy to with the results 😄

besrabasant commented 3 years ago

@xperator Can you share your modifications here?

HassanZahirnia commented 3 years ago

@besrabasant Sure buddy! 😄👍 I only changed a few lines so I can just list them here:

  1. First change I made was removing img-loader & imagemin-svgo & svg-vue3 from dependencies :

    dependencies() {
    return ['img-loader', 'imagemin-svgo', 'raw-loader', 'fs', 'svg-vue', 'svg-vue3'];
    }

    to :

    dependencies() {
    return ['raw-loader', 'fs', 'svg-vue'];
    }

    Note that I only removed svg-vue3 only because I'm using vue 2 and having svg-vue3 was causing dependency conflicts for me. You can keep it if you use vue 3.

  2. I removed img-loader & imagemin-svgo from webpack rules:

    rules: [
    {
        loader: 'raw-loader'
    },
    
    {
        loader: 'img-loader',
        options: {
            plugins: [
                require('imagemin-svgo')({ plugins: this.options.svgoSettings })
            ]
        }
    }
    ]

    and changed it to :

    rules: [
    {
        loader: 'raw-loader'
    },
    {
        loader: 'svgo-loader',
        options: {
            plugins: [
                'removeComments',
                'removeTitle',
                'removeDimensions',
            ],
        },
    },
    ]

    As you can see, we swapped img-loader for svgo-loader. I believe @danielstgt only used img-loader just to use it's imagemin-svgo plugin and since img-loader doesn't provide support for webpack 5 and therefore breaking the usage of this library with Mix 6.0.20 and above, we just had to find a replacement for that which in my case I found svgo-loader to be working just fine.

  3. And last ( extra step ) is probably to remove this package ( npm uninstall laravel-mix-svg-vue ) and also remove require('laravel-mix-svg-vue'); from webpack.mix.js and instead add the index.js located in the root directory of this project plus all the above changes to somewhere like resources/js and then require that file instead. Then you have to do npm i raw-loader svgo-loader svg-vue --save-dev since you're not using this package anymore and need these npm packages in your root package.json so you can use it.

I hope this helps someone. Hopefully @danielstgt can update the library with such changes so we can continue using laravel-mix-svg-vue instead of doing manual work 😄

danielstgt commented 3 years ago

I finally had the time to investigate this issue, thank you for your patience.

It is correct that the dependency img-loader with it's new version 4.0.0 isn’t compatible with webpack anymore. Laravel Mix has upgraded to that version: https://github.com/JeffreyWay/laravel-mix/pull/3004/commits/6c2cbad70d589411c7f2c54e338ac3ab35a84d15

The reason for this incomatibility with webpack lies in the usage of ESM (see https://stackoverflow.com/a/65550642/13204454) which is used here: https://github.com/vanwagonet/img-loader/blob/main/index.js#L14

Statements that img-loader doesn’t work with webpack 5 are a bit misleading, since your using Laravel Mix v6 which has been using that version for a long time now and you even got it to work with Laravel Mix 6.0.19. However, the issue actually roots to the imagemin plugin, which I saw isn't maintained anymore and the incompatibility issue has also bubbled up there too: https://github.com/imagemin/imagemin/issues/380

While searching for an alternative loader, I’ve came across the same one as @xperator. The usage of svgo-loader fixes all these issues since it doesn’t rely on imagemin or img-loader and even reduces the dependency weight for Laravel Mix SVG Vue.

A new version of Laravel Mix SVG Vue has been published https://github.com/danielstgt/laravel-mix-svg-vue/releases/tag/v0.3.4. It’s a non-breaking change, so you should be good to go with upgrading.

@xperator regarding your svg-vue3 dependency issue: What exactly causes the conflict? The package is just included for a better DX, if you’re not using it anywhere in your JS it won’t affect the output, it won’t even be there. I will close this issue here for now, but I will continue to track your replies if there are any compatibility issues.

HassanZahirnia commented 3 years ago

@danielstgt I only use Vue 2 and the svg-vue3 for me causes npm to throw an error each time I run install and update commands saying there is a conflict issue and it suggests to use --legacy-peer-deps with those commands which is really bothersome to do that every single time I want to work with npm... Not sure if this is possible or not but I think there should be a conditional to see which vue version is used by the user so include that dependency only.

Great update anyway 😀👍

danielstgt commented 3 years ago

@xperator could you tell me which packages exactly are causing the conflict? And if you could share your packages.json of that project, I could try to replicate and investigate the issue.

danielstgt commented 3 years ago

@xperator I've released a new version of Laravel Mix SVG Vue that doesn't require Vue.js 3 as a peer dependency in the svg-vue3 package.

Upgrading to this new version should fix your warnings:

npm install laravel-mix-svg-vue@^0.4.1