How to load image files with webpack file-loader
Regarding problem #1
Once you have the file-loader configured in the webpack.config, whenever you use import/require it tests the path against all loaders, and in case there is a match it passes the contents through that loader. In your case, it matched
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: "file-loader?name=/public/icons/[name].[ext]"
}
// For newer versions of Webpack it should be
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: 'file-loader',
options: {
name: '/public/icons/[name].[ext]'
}
}
and therefore you see the image emitted to
dist/public/icons/imageview_item_normal.png
which is the wanted behavior.
The reason you are also getting the hash file name, is because you are adding an additional inline file-loader. You are importing the image as:
'file!../../public/icons/imageview_item_normal.png'.
Prefixing with file!
, passes the file into the file-loader again, and this time it doesn't have the name configuration.
So your import should really just be:
import img from '../../public/icons/imageview_item_normal.png'
Update
As noted by @cgatian, if you actually want to use an inline file-loader, ignoring the webpack global configuration, you can prefix the import with two exclamation marks (!!):
import '!!file!../../public/icons/imageview_item_normal.png'.
Regarding problem #2
After importing the png, the img
variable only holds the path the file-loader "knows about", which is public/icons/[name].[ext]
(aka "file-loader? name=/public/icons/[name].[ext]"
). Your output dir "dist" is unknown.
You could solve this in two ways:
- Run all your code under the "dist" folder
- Add
publicPath
property to your output config, that points to your output directory (in your case ./dist).
Example:
output: {
path: PATHS.build,
filename: 'app.bundle.js',
publicPath: PATHS.build
},
webpack file-loader does not load background image
Adding esModule: false
inside the url-loader options the image helped me, though I'm not sure why, if someone has the same issue you should try this trick.
How to use webpack with static image files?
Webpack has a file-loader
which will handle copying static dependencies and resolving their URLs correctly:
https://webpack.js.org/loaders/file-loader/
Here is more in depth discussion about images specifically: https://webpack.js.org/guides/asset-management/#loading-images
How to load images in webpack 5 without using JavaScript
For all those who have a similar problem. You must first load the html-loader to be able to load images in your HTML files.
How to import every image with file-loader on React
Webpack V5:
Use require.context() to load all modules in a directory dynamically. This means you can load all
.svg
modules dynamically. You don't have toimport
them one by one.file-loader
isDEPRECATED
for v5, migrate to Asset Modules to allows one to use asset files (fonts, icons, etc) without configuring additional loaders.
Directory structure:
⚡ tree -L 5 -I 'node_modules'
.
├── dist
│ ├── app.js
│ ├── icon_truck1..svg
│ ├── icon_truck2..svg
│ └── icon_truck3..svg
├── package-lock.json
├── package.json
├── src
│ ├── app.js
│ └── assets
│ └── icon
│ ├── icon_truck1.svg
│ ├── icon_truck2.svg
│ └── icon_truck3.svg
└── webpack.config.js
4 directories, 11 files
src/app.js
:
function importAll(images) {
images.keys().forEach((image) => {
console.log(image);
});
}
const images = require.context("./assets/icon", true, /\.svg$/);
importAll(images);
webpack.config.js
:
const path = require("path");
module.exports = {
mode: "development",
entry: "./src/app.js",
output: {
filename: "app.js",
path: path.resolve(__dirname, "dist"),
publicPath: "",
},
module: {
rules: [
{
test: /\.(png|svg)$/i,
type: "asset/resource",
generator: {
filename: "[name].[ext]",
},
},
],
},
};
Execution result:
⚡ node dist/app.js
./icon_truck1.svg
./icon_truck2.svg
./icon_truck3.svg
Since you are using React-boilerplate
, try to use require.context()
like above directly.
file-loader creating extra file in root of dist folder
In the end it looks as if it was the css loader that was causing the issue - so I configured it to ignore urls and then changed from the file-loader plugin to the copy-webpack-plugin to copy the images:
Ignore urls with css loader
MiniCssExtractPlugin.loader,
{
// Use the css-loader to parse and minify CSS imports.
loader: 'css-loader',
options: {
sourceMap: true,
url: false,
}
},
Copy webpack plugin to copy images
const CopyPlugin = require("copy-webpack-plugin");
plugins: [
new CopyPlugin({
patterns: [
{
from: 'vue/images', // src location
to: 'images', // destination location in dist folder
},
],
options: {
concurrency: 100,
},
}),
]
Then in my css I could just reference the image as relative from the dist folders css to the dist folder images folders:
background-image: url(../images/loading.svg);
Seems a bit odd to me that I had to do it this way in order not to get the extra svg file so if anyone comes up with a better solution or knows how not to create the extra file, please feel free to answer
Related Topics
Tried to Load Angular More Than Once
Why Not Always Use the Index as the Key in a Vue.Js for Loop
Downloading Canvas Element to an Image
JavaScript to Check When the Browser Window Is Closed
Filtering an Array with a Function That Returns a Promise
Preventing Click Event with Jquery Drag and Drop
How to Serialize an Input File Object to JSON
Typescript: Deep Keyof of a Nested Object, with Related Type
Get Function Name in JavaScript
How to Set the Id Attribute of a HTML Element Dynamically with Angularjs (1.X)
Node.Js Variable Declaration and Scope
How to Listen for a Click-And-Hold in Jquery
Differencebetween Using Constructor VS State = {} to Declare State in React Component
Firing a Keyboard Event on Chrome
Jqgrid Gridunload/ Griddestroy
Es6 Modules Implementation, How to Load a JSON File
How to Wrap an Await/Async Try/Catch Block to Every Function