Using file-loader to load binary file in react - reactjs

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.

Related

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

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"/>

TypeScript with Relay: Can't resolve generated module

In my MessageItem.tsx component I have the following code:
const data = useFragment(
graphql`
fragment MessageItem_message on Message {
date
body
}
`,
message as any
);
After running relay-compiler --src ./src --schema ../../schema.graphql --language typescript --artifactDirectory ./src/__generated__, a module named MessageItem_message.graphql.ts gets generated.
But when I run the app it gives me an error:
Failed to compile.
./src/components/MessageItem.tsx
Module not found: Can't resolve
'./__generated__/MessageItem_message.graphql'
The reason is only components at the src root can refer to the right path (./__generated__), whereas components in a folder actually need to refer to the path (../__generated__) but it's not doing so.
How can I configure the path?
Edit .babelrc to point to the artifactDirectory
// .babelrc
{
"plugins": [
[
"relay",
{
"artifactDirectory": "./src/ui/graphql/types"
}
]
]
}
Remove "--artifactDirectory ./src/__generated__" from the relay-compiler options.
By default it seems the Relay compiler puts a "__generated__" directory in the directory with any source code containing GraphQL.
As a result any "./__generated__" references anywhere and at any level in the source code hierarchy now work as they should.
Thanks to #ThibaultBoursier for the pointer.
PS I wonder if the --artifcactDirectory option is just meant to be used to change the name of the artifact directory, rather than its location?
Just moments ago I ran into the same issue. The reason is that the relay-compiler is using the artifactDirectory setting to decide where to put the generated files, but the babel-plugin-relay exposing the graphql tag needs to get the very same argument otherwise it just attempts to include a colocated relative file.
I fixed it in my case by configuring the plugin with a babel-plugin-macros.config.js file as follows (where the artifactDirectory is the same as the one supplied to the relay-compiler):
module.exports = {
relay: {
artifactDirectory: "./src/ui/graphql/types",
},
};
This solution assumes you are using the macro via babel-plugin-macros, otherwise you might need to supply that argument via the .babelrc file but I have no experience with that unfortunately.

React - synchronous txt file to string?

I'm absolutely baffled by this one...
In my React project with create-react-app, I have a standalone js file in which I'd like to read a string from a txt file. The txt file is part of a project and not on a server.
I can't seem to find any answers of how to complete this seemingly trivial task in a synchronous manner. These would seem like obvious options:
import text from './data/text.txt';
const text = require('./data/text.txt');
Both lines above return a new path that includes /static/media/, which I can access through localhost in the browser, but that doesn't help me.
I can use JSON but it's almost a matter of principle at this point. It just seems ridiculous that I can't read a simple txt file.
You can use webpack raw-loader to directly import raw files into your project.
Install:
$ npm install raw-loader --save-dev
Config:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.txt$/i,
use: 'raw-loader',
},
],
},
};
Usage:
import text from './data/text.txt';
console.log(text); // This line will print out the content of the text file in the console

(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'
]
},
]

Webpack Config for Static Pug/HTML Pages

I'm transitioning a site to use Webpack, and I need a little help with configuration. I have a few pages written in Pug/Jade that are large and infrequently accessed (think Terms of Service or Privacy Policy). Most of my .jade files are Angular templates, so those are inlined in their components and it works well. These few files, however, I would like Webpack to compile into static HTML files served separately from the rest of the app. However, I would still like their file names to include a hash.
The basic idea I've come up with is like this:
In routes.ts:
$routeProvider.when('/_tos', templateUrl: require('./resources/terms-of-service.jade'))
In webpack.config.js's list of loaders:
{
test: /resources.*\.jade$/,
loaders: ['file?name=[name].[hash].html', 'pug-html']
}
I've tried that with various combinations of pug-loader, pug-html-loader (with and without the ?exports=false option), html-loader, extract-loader, extract-text-webpack-plugin, and file-loader, but everything I try has extra artifacts in the resulting .html file. E.g. it might start with module.exports =, or it might put \" everywhere in the file that should just have ".
Can anyone help?
Gah! I finally figured it out. I fundamentally misunderstood the way the list of loader works. I assumed only the first loader in the array that matched was used, but no, all loaders that match are used. (Though I'm still fuzzy on the details.) Here is a working configuration, where resources is the path to my "resources" directory:
loaders: [
{
test: /\.jade$/,
include: [resources],
loaders: ['file?name=[name].[hash].html', 'pug-html?exports=false']
},
{
test: /\.jade$/,
exclude: [resources],
loaders: ['pug-html?doctype=html']
}
]

Resources