При запуске моего приложения на сервере webpack dev все мои файлы изображений работают независимо от того, являются ли они тегами img в моем index.html или background-image: url () ..
Выполняя свой проект в производственной сборке, я получаю ошибки ссылки на файлы, которые не могут быть найдены.
GET file:///img/featured.png net::ERR_FILE_NOT_FOUND
GET file:///img/header-img1-1.jpg net::ERR_FILE_NOT_FOUND
Я добавил плагин copy webpack, так как думал, что это переместит все изображения из моей папки src / img в мою папку img внутри dist.
Должен ли я использовать опцию contentBase для webpack-dev-server? Или плагин copy-webpack-plugin не получает правильную ссылку? Супер запутанный
Дерево проекта:
- webpack.config.js
- package.json
- .babelrc
- src
- js
- index.js
- ...
- img
- ALL IMAGES LOCATED HERE
- scss
- layout
- landing.scss
- brands.scss
- base
- index.html
внутри Landing.scss я использовал
background: url('~/img/img-title.png')
то же самое в других файлах, например, в файлах brand.scss
background: url('~/img/img-title.png')
Что все работало нормально, и я думаю, что я запутался в том, как изображения ссылаются на загрузчик webpack / sass, и, похоже, не могу понять, как заставить пути к изображениям работать как для dev / production, я могу только кажется, работают по одному.
производственное дерево:
- dist
- css
- img
- js
- index.html
webpack.config.js:
const path = require('path');
const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractPlugin = new ExtractTextPlugin({
filename: 'css/main.css'
});
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ScriptExtPlugin = require('script-ext-html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = (env) => {
const isProduction = env.production === true
return {
entry: './src/js/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
use: 'babel-loader'
},
{
test: /\.css$|\.scss$/,
include: path.resolve(__dirname, 'src'),
use: extractPlugin.extract({
fallback: "style-loader",
use: [
{ loader: 'css-loader', options: { importLoaders: 2, sourceMap: true }},
{ loader: 'postcss-loader', options: { sourceMap: true, plugins: () => [autoprefixer] }},
{ loader: 'sass-loader', options: { sourceMap: true }},
],
})
},
{
test: /\.html$/,
use: ['html-loader']
},
{
test: /\.(jpe?g|png|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 1000,
name: 'img/[name].[ext]',
}
}
]
}
]
},
plugins: [
extractPlugin,
new HtmlWebpackPlugin({
filename: 'index.html',
inject: true,
template: './src/index.html'
}),
new ScriptExtPlugin({
defaultAttribute: 'async'
}),
new CleanWebpackPlugin(['dist']),
new CopyWebpackPlugin([
{from:'src/img',to:'img'}
]),
]
}
}


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Эй, я думаю, ваша проблема заключается в том, как вы ссылаетесь на изображение в своем scss.
В зависимости от структуры ваших папок это должно быть:
background: url('../../img/img-title.png')
Я думаю, вы используете другую структуру папок на производстве, чем на локальном, т.е. на локальном, это просто http: // локальный: ПОРТ / приложение, но на продукте он должен быть похож на http: // produrl / Some_Folder / приложение
Теперь перейдем к актуальной проблеме - это ваш загрузчик CSS.
По умолчанию css-загрузчик имеет url = true, в результате чего все URL-адреса отображаются относительно root. Следовательно, это работает для вас -
background: url('~/img/img-title.png')
но это не
background: url('../../img/img-title.png')
Просто установите url = false, и вы сможете указать относительный URL-адрес, и он будет правильно загружаться для всех сред.
Ах, спасибо вам огромное за это! Я никогда бы не подумал, что это css-loader, после прочтения в основном проблем с URL-адресами и загрузчиком sass.
Пожалуйста. В настоящее время я нахожусь в одной лодке, но мои проблемы еще хуже, поскольку задействованы компоненты узла.
Хотя принятый ответ может работать в вашем конкретном сценарии, я думаю, что есть лучшее решение, которое не включает отключение обработки css-loaderurl() и будет работать лучше в большинстве ситуаций.
~Когда вы используете ~ для импорта чего-либо в css, css-loader будет искать этот файл внутри node_modules. Ваши изображения находятся внутри папки src / img, поэтому вам нужно нет, чтобы импортировать ваши изображения тильды ~.
url() проблемаsass-loader не разрешает url() правильно, если они не находятся в том же каталоге входного файла.
В вашем конкретном примере вы импортируете некоторые URL-адреса внутри src / scss / layout / landing.scss и SRC / SCSS / макет /brands.scss, но я предполагаю, что ваша основная точка входа в scss находится внутри папки src / scss.
Примечание: для "основная точка входа в scss" я имею в виду файл scss, который вы импортируете в свою точку входа javascript SRC / JS / index.js
Итак, в вашем примере каждое изображение, импортированное в файл scss, который является нет внутри папки src / scss, будет вызывать ошибку.
Чтобы решить эту проблему, используйте разрешить-url-загрузчик, который разрешает относительные пути в операторах url () на основе исходного исходного файла.
[
{ loader: 'css-loader'}, // set `importLoaders: 3` if needed but should works fine without it
{ loader: 'postcss-loader'},
{ loader: 'resolve-url-loader' }, // add this
{ loader: 'sass-loader',
// sourceMap is required for 'resolve-url-loader' to work
options: { sourceMap: true }
}
]
CopyWebpackPlugin не является обязательнымВ зависимости от вашей конфигурации вам не нужен CopyWebpackPlugin, потому что ваши образы уже обрабатываются url-loader.
Примечание: url-загрузчик не выводит ваши изображения, а встраивает их, изображения выводятся загрузчик файлов, когда размер файла превышает ограничение (в байтах).
file-loader выведет ваши изображения в папку dist / img, потому что вы установили name: 'img/[name].[ext]', а вы установили output.path: path.resolve(__dirname, 'dist').
Вы можете изменить URL-адрес «publicPath» (относящийся к корню сервера), чтобы он соответствовал файловой структуре.
//webpack.config.js
...
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "assets/images/",
publicPath: "/other-dir/assets/images/"
}
}
]
}
]
}
Привет, @RobIsAnxious, я пробовал это, но получаю сообщение об ошибке сборки: Модуль не найден: Ошибка: не удается разрешить '../../img/image-title.png'