Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

dynamic image not found in react component #743

Closed
iMinosGFX opened this issue May 1, 2020 · 4 comments · Fixed by #757
Closed

dynamic image not found in react component #743

iMinosGFX opened this issue May 1, 2020 · 4 comments · Fixed by #757

Comments

@iMinosGFX
Copy link

iMinosGFX commented May 1, 2020

Hello,
Here I try to import and use an image in a react component, but this one is never found :

GET http://localhost:8000/[object%20Module] 404 (Not Found)

I try to access to defaultLogo.png which is in this tree:
https://prnt.sc/s92g2r

Here is my part of the code which is supposed to call and use it:
const pathToLogo = require('../../images/user_logo/${userData.logo_name}'); <img src={pathToLogo} alt=""/>

And here's my webpack encore config :
var Encore = require('@symfony/webpack-encore'); if (!Encore.isRuntimeEnvironmentConfigured()) { Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev'); } Encore .setOutputPath('public/build/') .setPublicPath('/build') .addEntry('app', './assets/js/app.jsx') .splitEntryChunks() .enableSingleRuntimeChunk() .cleanupOutputBeforeBuild() .enableBuildNotifications() .enableSourceMaps(!Encore.isProduction()) .enableVersioning(Encore.isProduction()) .configureBabelPresetEnv((config) => { config.useBuiltIns = 'usage'; config.corejs = 3; }) .enableSassLoader() .enableReactPreset() .copyFiles({ from: './assets/images/', to: 'images/[path][name].[hash:8].[ext]', pattern: /\.(png|jpg|jpeg|svg)$/ }) ; module.exports = Encore.getWebpackConfig();

Knowing that I'm working with "dev-server", but even "dev" or "build" doesn't work...
Any ideas? Do I misunderstand the syntax? I confess I have some trouble with Webpack encore...

Thanks a lot

@Kocal
Copy link
Member

Kocal commented May 1, 2020

Hi,

I think the issue come from the file-loader where your require('...') is now seen as an ES module.
The issue happens because file-loader has been upgraded from v1 to v6 in #731 and released in Encore v0.29.0:

For now you have two solutions:

  1. use require('../../images/user_logo/${userData.logo_name}').default
  2. or configure the option esModule like this (I haven't tested it locally, but it should works):
Encore
  // if you want to keep using `file-loader`
  .configureLoaderRule('images', rule => {
      rule.options.esModule = false;
  })

  // OR if you want to use `url-loader`
  .configureUrlLoader({
    images: {
      esModule: false
    }
  });

However, I think we should configure esModule: false in Encore by defaut, we broke some builds, even if in the Encore 0.29.0 changelog it says:

Unless you're doing custom configuration, it's unlikely you're affected

😅

What do you think @Lyrkan?

@iMinosGFX
Copy link
Author

@Kocal It works by adding .default to the require!

Thanks for the explanations, I admit it's one of the first projects I use webpack encore and I'm having a little trouble ^^'

Thank you very much!

@Lyrkan
Copy link
Collaborator

Lyrkan commented May 2, 2020

However, I think we should configure esModule: true in Encore by defaut, we broke some builds

Hm, yeah that could be an issue.

But since Webpack seems to be moving everything to ES modules instead of CommonJS (for good reasons) it's probably better to encourage the same thing and keep the default esModule: true.

There is a third "solution" to this issue : use ES imports instead of require(...) (I think that should be changed in our doc as well... people tend to think they are interchangeable but that's not the case):

// Simple imports - needs to be at the top of your module
import '../images/foo.png' as fooPath;

// Dynamic import
// Edit: Note that it will create an async chunk by default which only
// contains the path. If that's an issue it can be fixed relatively
// easily using the `/* webpackMode: "eager" */ comment or through the
// MinChunkSizePlugin.
import('../images/foo.png').then(({ default: fooPath }) => {
  // use fooPath there
});

// Dynamic import if you can use async functions
const { default: fooPath } = await import('../images/foo.png');

in the Encore 0.29.0 changelog it says:

Unless you're doing custom configuration, it's unlikely you're affected

Maybe we could change that to something along the lines of:

If you are importing images/fonts using the CommonJS syntax (require('foo.png')), you will now need to explicitely retrieve the default export (require('foo.png').default) in order to get the path of the file.
Imports done using the import keyword should not be affected.

(ping @weaverryan)

Edit: actually using dynamic imports would also require .default... but that was already the case before.

@stof
Copy link
Member

stof commented May 4, 2020

I vote for updating the changelog and keeping the default esModule: true

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
4 participants