React is not displaying img when using require, possible webpack setup issue - reactjs

I am attempting to use a map function to build a carousel from an array of objects. One of the objects is the image source. For some reason, using require to specify the img src no longer works. Here is a code snippet that shows the problem.
import myImg from '../images/myImg.jpg';
....
<img src={myImg} alt="This message is not expected to show"></img>
<img src="../images/myImg.jpg" alt="This message is expected to show"></img>
<img src={require("../images/myImg.jpg")} alt="Fails when message shows"></img>
The result is:
the 1st image displays without an alt message (this is expected)
the 2nd image does not display. The displayed alt message is: "This message is expected to show"
the 3rd image does not display. The displayed alt message is: "Fails when message shows"
I suspect there is something wrong in my wordpack.config settings. I am using file-loader. The code snippet for this is:
loaders: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader',
],
}
],
Is file-loader the wrong choice? Are my settings wrong? I tried this without file-loader and got the same results. This is strange because specifying the file src for an img using require used to work several months ago.

The answer is to use require('pathname').default versus require('pathname'). File-loader and webpack are not required.
Require returns a module vs the uri. One of the methods for require is default.
I discovered this by
console.log(require("./images/img.jpg"));
This returns a module versus the uri. Opening the module in console showed the available methods.
I then tried
console.log(require("./images/img.jpg").default);
This returns the same uri to the static image as import.
The obvious advantage of using require vs. import is that require is performed dynamically. The supplied path can come from an array or object. For example
var img = ["img0.jpg", "img1,jpg", "img2.jpg" ];
var i = 1;
<img src={require(./images/${i}).default} alt="some message"/>

Related

Using file-loader to load binary file in react

I am trying to load a file from a folder using a name from react props.
when I write this:
import FileImage from '!!file-loader!../public/uploads/file-1589134024728.file';
<img src={FileImage}/>
everything works (but is static). In elements I see:
<img src="368d70b7855164f45e8b1c68db4d549c.file">
[![working][1]][1]
But using this:
src={`!!file-loader!../public/uploads/${file}`}
will show as
<img src="!!file-loader!../public/uploads/file-1589134024728.file">
[![not working][2]][2]
GET http://localhost:8080/public/uploads/file-1589134024728.file 404 (Not Found)
I also tried
src={`../public/uploads/${file}`}
while webpack.config.js looks like that:
{
test: /\.(woff(2)?|ttf|eot|svg|file)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
]
}```
I believe I somehow need to return [contenthash].[ext] but how?
[1]: https://i.stack.imgur.com/ZDx6l.png
[2]: https://i.stack.imgur.com/lCnMd.png
These files look like they are uploaded, which means you don't have access to their names at build time. This is ok, you have the file name.
You need to make sure that the /uploads/ directory is available through your HTTP server, and then you can use src={'/uploads/' + file} to load the resource from that location.
Even if these are not user uploads, but static files that you provide, then you can put them in your public/uploads directory and still just link them using their location on the webserver. It's hard to be sure without knowing where file comes from.

How to play a wav (loaded from a URL) in React/html5?

I want to include an audio player that plays a wav file that is loaded from a URL in a React component. Although this should work straight forward with the HTML5 <audio> element, I cannot get it to play (I just see the control elements).
I tried to play a .mp3 with the same code, which works. I checked in Chrome and Safari which are supposed to support .wav - it works in neither of them. I tried to replace the <audio> element with a react-audio-player, a react-player and a react-sound element - none of them works.
When I open the URL, the sound is downloaded as an attachment.
render() {
const wavUrl = config.fileServer+this.props.values.id+".wav";
return (
<audio controls>
<source src={wavUrl} type="audio/wav" />
Your browser does not support the audio element.
</audio>
);
}
I expect to see an audio controller that starts playing the sound when I press play. Instead, I see an audio controller that does nothing when I press play, and that claims that the audio file is 0 seconds long. I checked the URL - it is correct if I past it as URL in my browser directly.
If you are using create-react-app you have to import the audio file.
import wavUrl from './path/to/file';
// ... rest of code here
As mentioned Kitanga, you can use import to load files from public (instead of full URL access), example:
import somefile from '../public/assets/mp3/test1.mp3'
then
Play extends Component {
...
}
render(
<Play file=somefile>
)
But if you found webpack error message at start: "You may need an appropriate loader to handle this file type..." then seems you need to load appropriate extension npm package to read it and configure webpack.config.js, example:
...
module: {
rules: [
{
test: /\.mp3$/,
loader: "file-loader"
},
...
]
...
...
if "file-loader" not installed then use example:
npm install --save file-loader

How to override a webpack loader based on specific require needs?

I'm building a documentation site in which I want to display demo code snippets.
With the styles, it was really straight forward, as my app is only including the main.scss, so I'm processing that file with all the necessary loaders to compile it, and any other scss file is loaded using the raw-loader to get the file as plain text.
The problem I'm having is at the moment of doing the same with my components. Unlike my styles, I need to include my components both when I want to render them using babel-loader, but I also want to import them as plain text for the demo showcase.
At first I thought of compromising using an inline loader at the require level
const componentCode = require('raw-loader!./path/to/component');
The problem with this approach is that by the time I try to do this import, the file has already been ran through babel-loader so I get the compiled version of the file instead of the original. I tried passing ?enforce=pre as a query parameter to the raw-loader inline, but this had no effect.
I was wondering if there is a way of defining a rule to override an import/require statement.
According to the webpack documentation
It's possible to overwrite any loaders in the configuration by prefixing the entire rule with !.
However, I can not find any examples of this. I tried the following, which compiled but crashed right after the first ! prefixed require without any errors
webpack.coonfig.js
{
test: /\.(js|jsx)$/,
exclude: [/node_modules/],
use: [
{
loader: 'babel-loader',
options: {
presets: ['env', 'react'],
},
},
],
},
{
test: /!*\.(js|jsx)$/,
enforce: "pre",
use: [
{
loader: 'raw-loader',
},
],
},
file.jsx
const componentCode = require('raw-loader!./path/to/component');
I also thought about reading the file using the fs but not sure if this will work. In the end the code will be compiled in its entirety by webpack and only the bundle will be published. Would this be the right approach?
Found my answer at Webpack - ignore loaders in require()?, Basically I need !! before the require to ignore the pre loaders and apply mine

image files not showing up - using webpack file loader

I have been trying to load images using webpack, but somehow it's not working.
here's the related code
{ test: /\.(jpe?g|png|gif)$/i, loader: 'file-loader?name=[name].[ext]' },
and here's one example of the component where the image should load
<ListItem
leftAvatar={
<Avatar src="assets/images-demo/avatars/128.jpg" />
}
but when the page loads, I get
http://localhost:8080/assets/images-demo/avatars/128.jpg 404 (Not Found)
In the network tab, I see the type of the images as text/html, (not sure why) and I see the initiator as DOMLazyTree. so, could you give me an idea of what's going wrong here?

(React + Webpack) Images Loading in Dev, but not Production (file-loader + image-webpack-loader)

Everything works great in development, but when I try to build for production, the images don't show up on the page. They do show up in proper folder (i.e. my production folder has an images subfolder with the images present). When I look at the folders (Sources) in the browser, the images folder is not present. It seems like the react build isn't aware of the folder for some reason even though webpack is building it properly. I'm guessing this is a react issue and not a webpack issue, but I'm still new to both. All of the resources that I have found seem to indicate that what I have should work, but I feel like I'm missing something.
webpack.config.js:
rules: [
...
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
'file-loader?name=[name].[ext]&publicPath=/&outputPath=images/',
'image-webpack-loader'
]
},
]
In use:
<img src={ require( './images/shopping-cart.png' ) } alt="shopping cart" />
Edit: I now have the image folder showing up with the image in it (ostensibly), however, the image is completely broken. Even just inspecting it in the browser from the folder does not work.
So it seems the answer was just to change '/' to './' and 'images/' to './images/'. I arrived at this through experimentation. Hopefully the answer helps someone else down the road.
rules: [
...
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
'file-loader?name=[name].[ext]&publicPath=./&outputPath=./images/',
'image-webpack-loader'
]
},
]

Resources