Здрасте! У меня есть проект на react с webpack. Во время работы webpack-dev-server все картинки загружаются, и всё хорошо работает. Но когда я выполняю команду npm run build и запускаю сборку, то пути для картинок webpack подставляет неверные, из-за чего возникают ошибки 404. В css файлах картинки загружаются при запуске и webpack-dev-server, и сборки. Пути для картинок я вставляю в виде строки. Пример:
const Head = ({ className }) => {
return (
<div className={classNames(classes.head, {}, [className])}>
<Button className={classNames(classes.shareBtn)} circle theme='clear'>
<img src='images/share.svg' alt='share' />
</Button>
</div>
)
}
export default Head
Все асеты у меня подгружаются из папки public в корне проекта. public папка содержит две подпапки images и fonts. Сам исходный код находится в папке src которая тоже в корне.
webpack
import webpack from 'webpack'
import { IWebpackConfig } from './types/config'
import { webpackLoaders } from './webpackLoaders'
import { webpackResolver } from './webpackResolvers'
import { webpackPlugins } from './webpackPlugins'
import type { Configuration as DevServerConfiguration } from 'webpack-dev-server'
import { webpackDevServer } from './webpackServer'
export default ({ mode, port, paths, isDev, isProd, analyze }: IWebpackConfig): webpack.Configuration => {
return {
mode: mode ?? 'development',
entry: paths.entry,
output: {
filename: '[name].[contenthash].js',
path: paths.output,
clean: true
},
module: {
rules: webpackLoaders({ mode, port, paths, isDev, isProd })
},
plugins: webpackPlugins({ mode, port, paths, isDev, isProd, analyze }),
resolve: webpackResolver({ mode, port, paths, isDev, isProd }),
devtool: isDev ? 'inline-source-map' : false,
devServer: webpackDevServer({ mode, port, paths, isDev, isProd })
}
}
webpack resolve
import { ResolveOptions } from 'webpack'
import { IWebpackConfig } from './types/config'
export const webpackResolver = ({ paths }: IWebpackConfig): ResolveOptions => {
const resolve = {
extensions: ['.tsx', '.ts', '.js'],
modules: [paths.src, 'node_modules'],
mainFiles: ['index'],
preferAbsolute: true,
alias: {
'*': paths.src
}
}
paths.public && resolve.modules.push(paths.public)
return resolve
}
webpack loaders
import { IWebpackConfig } from './types/config'
import webpack from 'webpack'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
export const webpackLoaders = ({ isDev, isProd }: IWebpackConfig): webpack.RuleSetRule[] => {
const babelLoader = {
test: /\.(js|jsx|tsx)$/,
exclude: '/node_modules/',
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
const tsLoader = {
test: /\.tsx?$/,
use: 'ts-loader',
exclude: '/node_modules/'
}
const cssLoader = {
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
exclude: '/node_modules/'
}
const sassLoader = {
test: /\.s[ac]ss$/,
use: [
isProd ? MiniCssExtractPlugin.loader : 'style-loader',
{
loader: 'css-loader',
options: {
modules: {
auto: (resPath: string) => Boolean(resPath.includes('.module.')),
localIdentName: isDev ? '[name]_[local]--[hash:base64:6]' : '[hash:base64:8]'
}
}
},
'sass-loader'
],
exclude: '/node_modules/'
}
const assetImages = {
test: /\.(png|svg|jpg|jpeg|gif|ico)$/i,
type: 'asset/resource',
generator: {
filename: 'static/[hash][ext]'
}
}
const assetFonts = {
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'static/[hash][ext]'
}
}
return [babelLoader, tsLoader, assetImages, assetFonts, cssLoader, sassLoader]
}
webpack plugins
import { IWebpackConfig } from './types/config'
import webpack from 'webpack'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
export const webpackPlugins = ({ paths, isProd, analyze }: IWebpackConfig): webpack.WebpackPluginInstance[] => {
const result: any[] = [
new HtmlWebpackPlugin({
template: paths.html
}),
isProd
? new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
chunkFilename: 'css/[name].[contenthash:8.css]'
})
: undefined,
new webpack.ProgressPlugin(),
analyze &&
new BundleAnalyzerPlugin({
openAnalyzer: false
})
]
return result
}