WebPack images not loading using file-loader - javascript

Currently, I have a webpack 5 project that requires several svg images and a background image. The svg images are coded into the template.html file. and the background image is referenced in the style.css file. When I run the build, none of the images are built on the webpage. They remain in hashed form (even though I am using a custom name within the file loader test.
Below is the current webpack config file:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/js/index.js',
},
plugins: [
new HtmlWebpackPlugin({
template: './src/template.html',
}),
],
devtool: 'inline-source-map',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'docs'),
},
module: {
rules: [
{
test: /\.css$/i,
use:['style-loader','css-loader'],
},
{
test: /\.(png|svg|jpg|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/images/'
}
}
]
},
{
test:/\.html$/,
use: [
'html-loader'
]
},
],
},
};
Below is a snippet to show how the svg
<div class="studyTime">
<div id="timeManager">
<div id="toDoButtons">
<button id="new"><img src="./assets/images/add.svg" alt=""></button>
<button id="clear"><img src="./assets/images/clear.svg" alt=""></button>
</div>
<div id="todo">
</div>
</div>
<img class="openDrawer" id="timeOpen" src="./assets/images/left.svg" alt="">
</div>
<div class="clock">
<div class="clock-face">
<div class="core"></div>
<div class="hand" id="hour-hand"></div>
<div class="hand" id="min-hand"></div>
<div class="hand" id="second-hand"></div>
</div>
</div>
Finally, here is an image of the program when built:
Build with image error
I have tried to use the file-loader format, as well as removing it. My file structure looks as follows:
file structure
I am not receiving any errors, and the images appear within the bundled code, but in hashed form and are not appearing in the live website.

you need html-loader and html webpack plugin . it Will rewrite your html file with hashed names.
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, './dist/js/index.html'),
template: path.resolve(__dirname, './src/template.html')
})
]
and replace svg rule with
module: {
rules: [
{
test: /\.svg/,
type: 'asset'
}
]
}

Related

webpack: inject javascript hashed file name in pug template

I'm using pug as my Node.JS view engine.
And I'm bundling my javascript files using webpack with hashname for cache busting.
The problem here is that I don't know how to include the bundled javascript file name in my pug template because every time it generates a new hash name.
How can I get the hash name generated from webpack and include it in my pug file?
This is how it should include the script file:
doctype html
html
include _head
body
script(src='/_bundle/main.649c4c4e6c8076189257.js')
My webpack.config.js
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode: "production",
entry: "./src/_public/js/index.js",
output: {
filename: "main.[contenthash].js",
path: path.resolve(__dirname, "src/_public/_bundle"),
},
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader", "css-loader", "sass-loader",
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
filetype: "pug",
}),
new HtmlWebpackPlugin({
filename: "./src/views/base.pug",
}),
],
}
Configure HtmlWebpackPlugin and HtmlWebpackPugPlugin properly:
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const HtmlWebpackPugPlugin = require('html-webpack-pug-plugin');
module.exports = {
mode: "production",
entry: "./src/_public/js/index.js",
output: {
filename: "main.[contenthash].js",
path: path.resolve(__dirname, "src/_public/_bundle"),
},
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader", "css-loader", "sass-loader",
],
},
],
},
plugins: [
new HtmlWebpackPugPlugin(),
new HtmlWebpackPlugin({
template: './src/views/base.pug',
filename: 'layout.pug',
}),
],
}
Install npm i HtmlWebpackPugPlugin. You will find the js and css references in the layout.pug file.
Actual solution for 2022.
Install the pug-plugin:
npm i -D pug-plugin
Using the pug-plugin:
the Webpack entry-point is the Pug file
all source scripts (JS/TS) can be loaded via require() in Pug
all source styles (CSS/SCSS) can be loaded via require() in Pug
Webpack config for Pug + JS + SCSS:
const path = require('path');
const PugPlugin = require('pug-plugin');
module.exports = {
output: {
path: path.join(__dirname, 'dist/'),
filename: 'js/[name].[contenthash:8].js' // output hashed filename of JS
},
entry: {
// define Pug files in entry:
index: './src/views/index.pug', // => index.html
about: './src/views/about/index.pug' // => about.html
// ...
},
plugins: [
// enable using Pug files as entry point
new PugPlugin({
extractCss: {
filename: 'css/[name].[contenthash:8].css' // output hashed filename of CSS
},
})
],
module: {
rules: [
{
test: /\.pug$/,
loader: PugPlugin.loader, // the Pug loader
},
{
test: /\.(css|sass|scss)$/,
use: ['css-loader', 'sass-loader']
},
],
},
};
Pug file ./src/views/index.pug:
doctype html
html
head
//- load source styles via require()
link(href=require('./path/to/scss/styles.scss') rel='stylesheet')
body
h1 Hello Pug!
//- load source scripts via require()
script(src=require('./path/to/js/index.js'))
Generated HTML:
<html>
<head>
<link href="/css/styles.f57966f4.css" rel="stylesheet">
</head>
<body>
<h1>Hello Pug!</h1>
<script src="/js/index.b855d8f4.js"></script>
</body>
</html>

How to load page contents with webpack 4 similar to jquery $.load()

i'm facing a problem with webpack 4 content load, how i used to do with jquery.
Here is what i'm trying to do with webpack 4
let say i have a page setting.html
<link rel="stylesheet" href="setting.css">
<div id="settingContent">
<!-- content -->
</div>
<script src="setting.js"></script>
on click of setting tab i want to load this page into index.html, #pageContent
index.html
<div id="pageContent">
</div>
with jquery i used to do it as shown below.
$('setting_tab').on('click',function(){
$('#pageContent').load('setting.html');
});
below is my webpack config file looks like
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: ['babel-polyfill', './src/js/index.js'],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/bundle.js'
},
devServer: {
contentBase: './dist'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html'
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};

Single click forces the event to fire twice (possible problem in Webpack)

I am new to Webpack and not so experienced in JavaScript either. I'm trying to set up a new project for the JS text editor. However, I noticed that after setting up the first addEventListener for the #btn button, the event gets fired twice.
I don't think that this behaviour is related to the event itself, since I have created three console.log functions. One is outside the eventListener, two remaining is inside. All of the three functions get console logged twice in the browsers console, which leads me to think that this might be related to Webpack config.
If anyone has a clue or and advice, please help.
HTML:
<main class="main__content">
<article class="text__editor-wrapper">
<h1 class=" ">Text Editor</h1>
<div class="toolbar">
<button id="btn" class="toolbar__option"><span class="fas fa-bold fa-2x"></span></button>
</div>
<div class="text__editor" contenteditable="true"></div>
</article>
</main>
index.js:
import "./scss/style.scss";
import '#fortawesome/fontawesome-free/css/all.css';
import '#fortawesome/fontawesome-free/js/all.js';
const btn = document.querySelector("#btn");
function format(command, value) {
document.execCommand(command, false, value);
}
console.log("Outside")
btn.addEventListener('click', function(e) {
e.preventDefault();
console.log("inside");
console.log(e.target);
format('bold');
});
webpack config file:
const path = require("path"),
HtmlWebpackPlugin = require("html-webpack-plugin"),
BrowserSyncPlugin = require("browser-sync-webpack-plugin"),
MiniCssExtractPlugin = require("mini-css-extract-plugin"),
UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
optimization: {
minimizer: [new UglifyJsPlugin()]
},
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 900
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
},
{
test: /\.(svg|eot|woff|woff2|ttf)$/,
use: [{
loader: "file-loader"
}]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader: "url-loader"
}]
},
{
test: /\.(sass|scss|css)$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader" }
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
}
You haven't given us your full HTML file, but I suspect this is where the problem lies.
Check your final (post-Webpack) index.html file - I suspect you're importing the main.js bundle in a <script> tag and also including the bundled JS.
This is because you're using Webpack to bundle your HTML (the HtmlWebpackPlugin plugin) and also creating a bundle (main.js) which you're importing somewhere in your HTML.

How to simply load images with src attribute with webpack 4?

Im stuck and can't get to work my webpack configuration for loading images with src attribute from HTML. I cloned a repo with full setup of webpack, but I know there is a way to simply customize and load images directly from HTML.
Webpack.config.js file:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: {
main: "./src/index.js"
},
output: {
path: path.join(__dirname, "../build"),
filename: "[name].bundle.js"
},
mode: "development",
devServer: {
contentBase: path.join(__dirname, "../build"),
compress: true,
port: 3000,
overlay: true
},
devtool: "cheap-module-eval-source-map",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader" // transpiling our JavaScript files using Babel and webpack
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"postcss-loader", // Loader for webpack to process CSS with PostCSS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: [
{
loader: "file-loader", // This will resolves import/require() on a file into a url
and emits the file into the output directory.
options: {
name: "[name].[ext]",
outputPath: "assets",
}
},
]
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: {
attrs: ["img:src", ":data-src"],
minimize: true
}
}
}
]
},
plugins: [
// CleanWebpackPlugin will do some clean up/remove folder before build
// In this case, this plugin will remove 'dist' and 'build' folder before re-build again
new CleanWebpackPlugin(),
// The plugin will generate an HTML5 file for you that includes all your webpack bundles
in
the body using script tags
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html"
}),
Before this project I was able to make that images would simply load from HTML but now ironicly im stuck and can't get this working.
Any help will be very appriciated.
When loading a image directly form HTML, I get the following error:
Error: Child compilation failed:
Module not found: Error: Can't resolve '
./src/assets/images/portret.jpg' in '/home/viktoras/www/sites/painter-new/src':
You can do this:
<img src="<%=require('./src/assets/logo.png')%>">
Plugin Conf
$new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html'
}),

Webpack and Angular HTML image loading

I have been breaking my head with webpack and angular. This might have a simple answer but I cant figure it out. I have read almost every answer here in stack overflow on this topic to no avail.
I have an html page like this (also other template that have images):
<body>
<img ng-src="../images/angular-webpack.png">
<md-button class="md-primary md-raised">
Button
</md-button>
</body>
I also have a webpack config:
var webpack = require('webpack');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var path = require('path');
module.exports = {
context: path.resolve(__dirname + '/src'),
entry: ['./js/core/app.module.js'],
output: {
path: './release',
publicPath:'/',
filename: 'app.js'
},
module: {
loaders: [
{
test: /\.html/,
exclude: 'node_modules',
loader: 'raw-loader'
},
{
test: /\.css/,
exclude: 'node_modules',
loader: 'style-loader!css-loader'
},
{
test: /\.(jpe?g|png)$/i,
exclude: 'node_modules',
loader: 'url-loader?limit=8192!img'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new CopyWebpackPlugin([
{from: './index.html', to: './index.html'}
], {
ignore: [
'*.txt',
{glob: '**/*', dot: true}
]
})
],
devServer: {
contentBase: './release'
},
watch: true
};
...but i do not see my images loading. I have tried url-loader, file-loader with publicPath and without it. I am confused, I do not know how to format the webpack config or the html image tag for it to work.
Anyone has any experience on getting images to work with webpack? Also I do not want to include my images in the controllers or any other js file. I want the images to be declared in the html page.
The raw-loader is supposed to turn a text file into a CommonJS module that exports the file contents as a string – nothing more.
If you want webpack to recognize the file as HTML and all its references in it, you need the html-loader. The html-loader parses the given file with an HTML parser and picks up references to other files within attributes. By default, that is only <img src="...">. In your case, you need to tell the html-loader to also look for ng-src attributes, like this:
// webpack.config.js
...
loaders: [{
test: /\.html$/,
loaders: [
"html?" + JSON.stringify({
attrs: ["img:src", "img:ng-src"]
})
]}
]

Categories