Use public path of css image with webpack instead of copying over the image or using inline encoding - javascript

I am trying to set up webpack so I can have it with wordpress. I have a file structure like the following:
-assets/
-img
-dist/
-src/
-js
index.js
-scss
webpack.config.js
...etc
I have webpack configured to build into the dist file.
I want to be able to import background images into my css in the src file from the assets file which I can do. But then with webpack's assets module found here https://webpack.js.org/guides/asset-modules/
{
test: /\.(jpg|png|svg|gif)$/,
type: 'asset',
},
when it builds it either copys the image over with asset/resource so then I basically have 2 of the same images in the project. Or it encodes it directly into the css in base64 with assets/inline or source with assets/source. This all seems pointless in my case.
Is there a way to have webpack just use the relative path in the assets folder instead of duplicating the image or encoding it? So instead of compiling to something like:
body: {
background: url(/[hashed-from-webpack].jpg);
}
it just compiles to
body: {
background: url(../assets/img/myimage.jpg);
}
Here is the entire webpack config file:
const path = require('path')
const rootDir = path.join(__dirname, '')
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
entry: {
app: path.join(rootDir, 'src/js', 'app'),
},
output: {
filename: '[name].js',
path: path.join(rootDir, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.s[ac]ss$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin(),
new BrowserSyncPlugin({
host: 'localhost',
port: 3000,
proxy: 'http://localhost/wordpress/',
files: ['**/*.php'],
}),
],
devServer: {
compress: true,
port: 3000,
open: true,
},
}

Related

Webpack multiple entries under certain urls

Hey I have this project which has this structure:
bundler -> webpack.common.js
src -> main.js, index.html, styles.css
package.json
node_modules... the rest doesnt matter really
It is set up like when I do: npm run dev webpack creates a live server using my current main.js for my index.html
The webpack.common.js looks like this:
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCSSExtractPlugin = require("mini-css-extract-plugin");
const path = require("path");
module.exports = {
entry: path.resolve(__dirname, "../src/current_script.js"),
output: {
hashFunction: "xxhash64",
filename: "bundle.[contenthash].js",
path: path.resolve(__dirname, "../dist"),
},
devtool: "source-map",
plugins: [
new CopyWebpackPlugin({
patterns: [{ from: path.resolve(__dirname, "../static") }],
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "../src/index.html"),
minify: true,
}),
new MiniCSSExtractPlugin(),
],
module: {
rules: [
// HTML
{
test: /\.(html)$/,
use: ["html-loader"],
},
// JS
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
// CSS
{
test: /\.css$/,
use: [MiniCSSExtractPlugin.loader, "css-loader"],
},
// Images
{
test: /\.(jpg|png|gif|svg)$/,
type: "asset/resource",
generator: {
filename: "assets/images/[hash][ext]",
},
},
// Fonts
{
test: /\.(ttf|eot|woff|woff2)$/,
type: "asset/resource",
generator: {
filename: "assets/fonts/[hash][ext]",
},
},
],
},
};
```
Now my question is how can I define multiple entries under certain URLs.
So for example now under localhost/ it will redirect me to index.html using my main.js
Is there a way of having localhost/2 use my index.html with another js file like main2.js

Webpack 5 - Scss relative urls won't load images

I have my scss and my images in folders at the same level.
File structure
styles
app.scss
images
my-image.jpg
Am trying to import my image like so
app.scss
body {
background: url(../images/my-image.jpg);
}
I have a simple webpack configuration to load scss and images.
webpack.config.js
const path = require("path");
module.exports = {
entry: "./resources/index.js",
resolve: {
alias: {
resource: path.resolve(__dirname, "resources/images"),
},
},
output: {
path: path.resolve(__dirname, "dist"),
publicPath: "/dist",
filename: "main.js",
assetModuleFilename: "[name][ext][query]",
clean: true,
},
mode: "production",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.(png|jpg)/,
type: "asset",
},
],
},
};
Later on I tried to use resolve-url-loader between css-loader and scss-loader which seemed promising. But also to no avail.
The build isn't throwing any errors. But the page doesn't open the image.
Thank you for any help you give me my bros and bronettes.
At the end the problem with the images was simply in the publicPath on the web.config.js file.
Changing it from dist/ to /dist did the job.
const path = require("path");
module.exports = {
...
output: {
path: path.resolve(__dirname, "dist"),
publicPath: "dist/", //This is where the issue was
filename: "main.js",
assetModuleFilename: "[name][ext][query]",
clean: true,
},
...
};
Let this be a warning for all ye who enter webpack.

webpack - scss cannot resolve background-image url

In my scss file, I use background-image: url("../../../assets/images/home/banner-mobile.png");
The application runs successfully, but no background image is shown:
The background image URL is not resolved.
webpack/webpack.base.js
const webpack = require("webpack");
const path = require("path");
const utils = require("./utils");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.jsx",
resolve: {
alias: {
"#": utils.resolve("src")
},
extensions: ["*", ".js", ".jsx"],
fallback: {...},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
},
{
loader: "sass-loader"
},
{
loader: "sass-resources-loader",
options: {
resources: ["./src/assets/scss/main.scss"],
},
},
],
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 8192
},
},
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: "public/index.html",
filename: "index.html",
inject: true,
})
],
};
webpack/webpack.dev.js
const { merge } = require("webpack-merge");
const base = require("./webpack.base");
const Dotenv = require("dotenv-webpack");
module.exports = merge(base, {
mode: "development",
devtool: "inline-source-map",
output: {
publicPath: '/',
},
devServer: {
port: 3000,
static: true,
static: 'dist'
},
plugins: [new Dotenv({ path: "./.env.development" })],
});
Update 1
When I view the png in Web Inspector > Sources:
When I open the image with its URL in the browser:
Update 2:
When I build and view the image via VSCode, it shows below:
Not sure if the below file-is related
webpack/Util.js
const path = require('path')
module.exports = {
resolve: function(dir) {
return path.join(__dirname, '..', dir)
}
}
Since you're using Webpack 5, I'd recommend using Asset Modules instead of the deprecated loaders
module: {
rules: [
// ...
{
test: /\.(png|jpg|gif)$/i,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 8192
}
}
}
]
}
I suspect you were running into a resource handling duplication issue as noted in the documentation...
When using the old assets loaders (i.e. file-loader / url-loader / raw-loader) along with Asset Module in webpack 5, you might want to stop Asset Module from processing your assets again as that would result in asset duplication. This can be done by setting asset's module type to 'javascript/auto'.
I use file-loader as shown in this rule, it allow me to preserve the file name and relative path, so having my folder structure like assets > images, I just have to strip "assets" from the path:
{
test: /\.(gif|png|jpg|jpeg)$/,
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
outputPath: (file) => {
const p = file.split('assets/')[1];
return p;
},
},
},
This will let you with all images within "assets" folder right into the root bundle and every path will be replicated (ex. assets/images/home/banner.png will be on images/home/banner.png in your dist directory), just be sure all your images are inside your assets folder to avoid getting name conflicts
Solution
After a long search, the only solution I found is to use ~ to reference the initial project directory and accessing public folder from there.
background-image: url("~/public/images/icon.png");
And this is working fine for me :)
OR And the other alternative would be to move images to the src directory, and this won't be a problem since webpack would pack them in a folder called static/media as static files

Can webpack change the source of assets?

Below is my webpack.config.js. I'm working on a phaser game with a restAPI. My assets are in a folder off the root. My problem is I compiled with webpack and it changed the code in the boot scene of phaser to look for my assets in 'build/assets'. There is no such folder, so in the browser it's giving me the 404 not found errors. Is there a way to prevent this in the webpack.config? Or should I just copy the assets folder inside the build folder?
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/build/',
filename: 'project.bundle.js',
},
module: {
rules: [
{
test: /\.m?js$/,
use: { loader: 'babel-loader' },
exclude: /node_modules/,
},
{
test: [/\.vert$/, /\.frag$/],
use: 'raw-loader',
},
],
},
plugins: [
new webpack.DefinePlugin({
'CANVAS_RENDERER': JSON.stringify(true),
'WEBGL_RENDERER': JSON.stringify(true),
}),
],
};

push assets folder to public directory with webpack

I'm using Webpack for the first time. Currently everything is being served up quite nicely. My problem is when I'm trying to build a dist folder. Currently I get my index.html and bundle.js files but I can't figure out how to push my assets to the dist folder.
I have file-loader loaded up but it doesn't actually seem to do what I want it to and none of the google searches I've run are telling me what I need to know. Below is my config file. Can someone lead a horse to water? Also once I get it running do I need to import all of images to my React components?
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/'
},
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.scss$/, use: [ 'style-loader', 'css-loader', 'sass-loader' ]},
{ test: /\.(png|jpe?g|svg|)$/, use: { loader: 'file-loader', options: }}
]
},
devServer: {
historyApiFallback: true,
},
plugins: [
new HtmlWebpackPlugin({
template: 'app/index.html'
})
]
};
Looks like I just needed to use Copy-Webpack-Plugin.
To copy all the assets from 'app/assets/' to 'dist/assets/' I just needed to do:
plugins: [
new CopyWebpackPlugin([
{ from: 'app/assets', to: 'assets' }
])
]
First install copy webpack plugin:
npm i copy-webpack-plugin
Then in the webpack.config.json:
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "src/public", to: "" } //to the dist root directory
],
}),
],
};

Categories

Resources