Answer the question
In order to leave comments, you need to log in
Webpack 5 how to setup proper image bundle?
Good day.
The problem is this, I just master webpack, first I assembled it myself, but then I found a ready-made assembly and tried to bring it to mind.
npm run build fails to properly pass images to dist.
The problem is that image files are added to the root with a unique hash instead of going into the assets/images folder with their name.
In the styles, the addresses of the pictures are also changed to those that are in the root, and not in the folder you need, although they were originally specified in the publick/images folder.
PS I hope I explained it in an accessible
way The file system is as follows
const path = require('path')
module.exports = {
// Source files
src: path.resolve(__dirname, '../src'),
// Production build files
build: path.resolve(__dirname, '../dist'),
// Static files that get copied to build folder
public: path.resolve(__dirname, '../public'),
const paths = require('./paths')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// Where webpack looks to start building the bundle
entry: [paths.src + '/index.js'],
// Where webpack outputs the assets and bundles
output: {
path: paths.build,
filename: '[name].bundle.js',
publicPath: '/',
},
// Customize the webpack build process
plugins: [
// Copies files from target to destination folder
new CopyWebpackPlugin({
patterns: [
{
from: paths.public,
to: 'assets',
globOptions: {
ignore: ['*.DS_Store'],
},
},
],
}),
// Generates an HTML file from a template
// Generates deprecation warning: https://github.com/jantimon/html-webpack-plugin/issues/1501
new HtmlWebpackPlugin({
title: 'webpack Boilerplate',
template: paths.src + '/login.html', // template file
filename: 'index.html', // output file
}),
],
// Determine how modules within the project are treated
module: {
rules: [
// JavaScript: Use Babel to transpile JavaScript files
{test: /\.js$/, exclude: /node_modules/, use: ['babel-loader']},
// Styles: Inject CSS into the head with source maps
{
test: /\.(scss|css)$/,
use: [
'style-loader',
{loader: 'css-loader', options: {sourceMap: true, importLoaders: 1}},
{loader: 'postcss-loader', options: {sourceMap: true}},
{loader: 'sass-loader', options: {sourceMap: true}},
],
},
// Images: Copy image files to build folder
{test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource'},
// Fonts and SVGs: Inline files
{test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline'},
],
},
}
const paths = require('./paths')
const webpack = require('webpack')
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
// Set the mode to development or production
mode: 'development',
// Control how source maps are generated
devtool: 'inline-source-map',
// Spin up a server for quick development
devServer: {
historyApiFallback: true,
contentBase: paths.build,
open: true,
compress: true,
hot: true,
port: 3000,
},
plugins: [
// Only update what has changed on hot reload
new webpack.HotModuleReplacementPlugin(),
],
})
const paths = require('./paths')
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = merge(common, {
mode: 'production',
devtool: false,
output: {
path: paths.build,
publicPath: '/',
filename: 'js/[name].[contenthash].bundle.js',
},
plugins: [
// Removes/cleans build folders and unused assets when rebuilding
new CleanWebpackPlugin(),
// Extracts CSS into separate files
// Note: style-loader is for development, MiniCssExtractPlugin is for production
new MiniCssExtractPlugin({
filename: 'styles/[name].[contenthash].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.(scss|css)$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: false,
},
},
'postcss-loader',
'sass-loader',
],
},
],
},
optimization: {
minimize: true,
minimizer: [new OptimizeCssAssetsPlugin(), "..."],
// Once your build outputs multiple chunks, this option will ensure they share the webpack runtime
// instead of having their own. This also helps with long-term caching, since the chunks will only
// change when actual code changes, not the webpack runtime.
runtimeChunk: {
name: 'runtime',
},
},
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000,
},
})
{
"name": "webpack-boilerplate",
"version": "2.0.0",
"description": "Sensible webpack 5 boilerplate using Babel and PostCSS with a hot dev server and an optimized production build.",
"main": "index.js",
"author": "Tania Rascia",
"license": "MIT",
"scripts": {
"start": "cross-env NODE_ENV=development webpack serve --config config/webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config config/webpack.prod.js"
},
"keywords": [
"webpack",
"webpack 5",
"webpack boilerplate"
],
"devDependencies": {
"@babel/core": "^7.12.1",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"babel-loader": "^8.1.0",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^6.2.1",
"cross-env": "^7.0.2",
"css-loader": "^5.0.0",
"css-minimizer-webpack-plugin": "^1.1.5",
"html-webpack-plugin": "^5.0.0-alpha.7",
"mini-css-extract-plugin": "^1.0.0",
"node-sass": "^4.14.1",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss-loader": "^4.0.4",
"postcss-preset-env": "^6.7.0",
"sass-loader": "^10.0.3",
"style-loader": "^2.0.0",
"webpack": "^5.1.3",
"webpack-cli": "^4.0.0",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^5.2.0"
},
"repository": {
"type": "git",
"url": "[email protected]:taniarascia/webpack-boilerplate"
},
"dependencies": {}
}
Answer the question
In order to leave comments, you need to log in
If you understand your problem correctly, you need to correctly specify the file name in the file loader (you are using a new feature (asset / resource), if you can specify the file name in it, then in it, if not, replace it with the file loader).
Filename - the path to the file.
{
loader: 'file-loader',
options: {
publicPath: '../',
name: `assets/image/[name].[ext]`,
}
}
Correct Solution for Webpack 5
module.exports = {
...
output: {
...
assetModuleFilename: 'assets/images/[name][ext]'
},
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
};
I contacted the developer of the assembly. Got the following response:
Images that are used in a script should be stored in src/images. Public stores files that are used directly in template.html. In the markup, "../public" should be replaced with "./assets", for example:
<div id="root"> <!-- на самом деле изображение хранится в ../public/images --> <img src="./assets/images/example.jpg" /> </div>
Another point: in webpack.common.js and webpack.prod.js, the value of publicPath in output must be changed to "./" (put a dot at the beginning).
To set the path for different types of assets (for example, for fonts), you need to add the 'asset/resource' type to the rules:
{
test: /\.(gif|png|jpe?g|svg)$/i,
type: 'asset/resource',
},
{
test: /\.(ttf|eot|woff2?)$/i,
type: 'asset/resource',
},
output: {
...
assetModuleFilename: pathData => {
const filepath = path.dirname(pathData.filename).split('/').slice(1).join('/');
return `${filepath}/[name][ext]`;
},
},
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question