Изображения не отображаются в производственной сборке, только в dev (webpack / sass-loader)

При запуске моего приложения на сервере 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'} 
	  ]), 
	]
  }
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
0
2 770
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Эй, я думаю, ваша проблема заключается в том, как вы ссылаетесь на изображение в своем scss.

В зависимости от структуры ваших папок это должно быть:

background: url('../../img/img-title.png')

Привет, @RobIsAnxious, я пробовал это, но получаю сообщение об ошибке сборки: Модуль не найден: Ошибка: не удается разрешить '../../img/image-title.png'

joshuaaron 01.04.2018 06:07
Ответ принят как подходящий

Я думаю, вы используете другую структуру папок на производстве, чем на локальном, т.е. на локальном, это просто 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.

joshuaaron 02.04.2018 03:37

Пожалуйста. В настоящее время я нахожусь в одной лодке, но мои проблемы еще хуже, поскольку задействованы компоненты узла.

Bikas 02.04.2018 11:13

Хотя принятый ответ может работать в вашем конкретном сценарии, я думаю, что есть лучшее решение, которое не включает отключение обработки 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/"
            }
          }
        ]
      }
    ]
  }

Другие вопросы по теме