Laravel-mix: Vue asset images not loading

Created on 8 Jan 2021  路  7Comments  路  Source: JeffreyWay/laravel-mix

  • Laravel Mix Version: 6.0.9
  • Node Version: 15.5.1
  • NPM Version: 7.3.0
  • OS: Mac OS Big Sur 11.1

Description:

After upgrading to Laravel Mix 6 my build runs successfully but images referenced from the assets folder no longer are loading.

Steps To Reproduce:

Running an existing Laravel v8.21.0 project with Laravel/UI Vue auth scaffolding, after upgrading Laravel Mix to version 6 images referenced from the assets folder in Vue don't err out on build but display as broken images in the browser.

Referencing images as such:

<img src="../assets/logo.png" alt="Logo">

When I inspect the image I see this:

<img src="[object Module]" alt="Logo">

Any help would be greatly appreciated. Thanks!

Most helpful comment

Apparently its a bug with vue-loader which Mix uses. Here is my workaround solution. This only sets esModule to false on the images file-loader.

mix.override(webpackConfig => {
  // BUG: vue-loader doesn't handle file-loader's default esModule:true setting properly causing
  // <img src="[object module]" /> to be output from vue templates.
  // WORKAROUND: Override mixs and turn off esModule support on images.
  // FIX: When vue-loader fixes their bug AND laravel-mix updates to the fixed version
  // this can be removed
  webpackConfig.module.rules.forEach(rule => {
    if (rule.test.toString() === '/(\\.(png|jpe?g|gif|webp)$|^((?!font).)*\\.svg$)/') {
      if (Array.isArray(rule.use)) {
        rule.use.forEach(ruleUse => {
          if (ruleUse.loader === 'file-loader') {
            ruleUse.options.esModule = false;
          }
        });
      }
    }
  });
});

All 7 comments

Hi,
I faced a similar issue yesterday.
The assets were copied successfully but the src path were not correctly rendered (object instead of a string)

It turned out this was caused by the embedded file-loader, which by default output files with ES6 syntax.
So I had to override the original configuration
mix.override(webpackConfig => { // Firstly try to find the rule(s) where the file-loader is implyed console.log(webpackConfig.modules.rules) // Then modify the loader configuration webpackConfig.module.rules[2].use[0].options.esModule = false; });
Hope it can help.

@Aiwings Thanks for the response.

I was also able to get the image loaded by doing this:

<img :src="require('./assets/logo.png').default" alt="Logo">

Both of these solutions feel kinda ugly to me tbh.

Apparently its a bug with vue-loader which Mix uses. Here is my workaround solution. This only sets esModule to false on the images file-loader.

mix.override(webpackConfig => {
  // BUG: vue-loader doesn't handle file-loader's default esModule:true setting properly causing
  // <img src="[object module]" /> to be output from vue templates.
  // WORKAROUND: Override mixs and turn off esModule support on images.
  // FIX: When vue-loader fixes their bug AND laravel-mix updates to the fixed version
  // this can be removed
  webpackConfig.module.rules.forEach(rule => {
    if (rule.test.toString() === '/(\\.(png|jpe?g|gif|webp)$|^((?!font).)*\\.svg$)/') {
      if (Array.isArray(rule.use)) {
        rule.use.forEach(ruleUse => {
          if (ruleUse.loader === 'file-loader') {
            ruleUse.options.esModule = false;
          }
        });
      }
    }
  });
});

@tinyfly you have a link to an open issue for that?

@ethanclevenger91 Here you go: https://github.com/vuejs/vue-loader/issues/1612

Apparently its a bug with vue-loader which Mix uses. Here is my workaround solution. This only sets esModule to false on the images file-loader.

mix.override(webpackConfig => {
  // BUG: vue-loader doesn't handle file-loader's default esModule:true setting properly causing
  // <img src="[object module]" /> to be output from vue templates.
  // WORKAROUND: Override mixs and turn off esModule support on images.
  // FIX: When vue-loader fixes their bug AND laravel-mix updates to the fixed version
  // this can be removed
  webpackConfig.module.rules.forEach(rule => {
    if (rule.test.toString() === '/(\\.(png|jpe?g|gif|webp)$|^((?!font).)*\\.svg$)/') {
      if (Array.isArray(rule.use)) {
        rule.use.forEach(ruleUse => {
          if (ruleUse.loader === 'file-loader') {
            ruleUse.options.esModule = false;
          }
        });
      }
    }
  });
});

I had this issue when i've updated laravel mix from 5 to 6

Got some [object Module] urls for thirds libraries like trumbowyg or remixicons and this solved the issue

Thanks, i hope there will be a fix for this or an option to set the esModule option for file-loader !

@tinyfly I finally got around to implementing your solution and it works great! Thank you for that and for linking to the issue in vue-loader.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Cheddam picture Cheddam  路  3Comments

RomainGoncalves picture RomainGoncalves  路  3Comments

sdebacker picture sdebacker  路  3Comments

hasnatbabur picture hasnatbabur  路  3Comments

terion-name picture terion-name  路  3Comments