URL-загрузчик Webpack или загрузчик файлов не работает, реагируйте на приложение

Изображения не загружаются в браузере с помощью Webpack 4 ни с загрузчиком URL, ни с загрузчиком файлов. Маленькие изображения не находятся в URL-адресе данных (или, если они есть, браузер их не показывает), и сетевые запросы файлов не выполняются с помощью загрузчика файлов.

Nginx правильно обслуживает изображения в https://{server}/images/image_name.png, но не https://{server}, и на сетевой панели веб-инспектора не выполняются сетевые вызовы для изображений.

На данный момент лучше всего предположить, что загрузчик URL-адресов Webpack или загрузчик файлов не должны генерировать правильный URL-адрес. Не удается найти хост при поиске URL-адреса в app.bundle.js. Я пробовал в течение нескольких дней каждую комбинацию publicPath, outputPath и т. д. из всех других сообщений stackoverflow, ничего не работает.

Есть ли способ просмотреть URL-адрес, который генерирует веб-пакет, помимо поиска js? Конфигурация веб-пакета неправильная? Совет по устранению неполадок?

Вот как я обрабатываю изображения в коде:

import nav_logo from "Images/white_nav_logo.svg";

<img src={nav_logo} />

Вот мой webpack.common.js:

module.exports = {
  mode: mode,
  entry: {
    app: ["./src/js/app.js"]
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: '[name].bundle.js',
    publicPath: '/',
    chunkFilename: '[name].bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.(sc|c|)ss$/,
        issuer: {
          exclude: /\.less$/,
        },
        use: [
          {
            loader:  'style-loader',
            options: {
            },
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              localIdentName: '[name]-[local]-[hash:base64:5]',
            },
          },
        ],
      },

      {
        test: /\.less$/,
        use: [
          {
            loader:  'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
            },
          },
        ],
      },
      {
        test: /\.(jsx?)/,
        exclude: ["/node_modules", "/src/js/elm"],
        use: [
          { loader: "babel-loader?cacheDirectory=true",
          }
        ]
      },
      {
        test: /\.scss$/,
        issuer: /\.less$/,
        use: {
          loader: './src/js/sassVarsToLess.js'
        }
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000,
              name: 'images/[name].[ext]',
            }
          },
          {
            loader: "image-webpack-loader",
            options: {
              disable: true,
              mozjpeg: {
               progressive: true,
               quality: 65
              },
              // optipng.enabled: false will disable optipng
              optipng: {
               enabled: true,
              },
              pngquant: {
               quality: '65-90',
               speed: 4
              },
              gifsicle: {
               interlaced: false,
              },
              // the webp option will enable WEBP
              webp: {
               quality: 75
              }
            }
          },
        ],
      },
      {
        test: /\.(ttf|otf|eot|woff2?)$/,
        loader: "file-loader",
        options: {
          name: 'fonts/[name].[ext]',
        }
      }
    ],
    noParse: [/\.elm$/]
  },
  node: {
    fs: 'empty'
  },
  plugins: [
    new Dotenv(),
    new CopyWebpackPlugin([{
      from: "./src/assets/css",
      to: "css"
    },
  ]),
  ]
};

и webpack.prod.js

module.exports = merge(common, {
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.(sc|c|)ss$/,
        issuer: {
          exclude: /\.less$/,
        },
        use: [
          {
            loader:  MiniCssExtractPlugin.loader,
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              localIdentName: '[name]-[local]-[hash:base64:5]',
            },
          },
        ],
      },
      {
        test: /\.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
            }
          },
        ],
      },
      {
        test: /\.(jsx?)/,
        exclude: ["/node_modules", "/src/js/elm"],
        use: [
          { loader: "babel-loader?cacheDirectory=true",
          }
        ]
      },
      {
        test: /\.scss$/,
        issuer: /\.less$/,
        use: {
          loader: './src/js/sassVarsToLess.js' // Change path if necessary
        }
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000,
              name: 'images/[name]-[hash:8].[ext]'
            }
          },
          {
            loader: "image-webpack-loader",
            options: {
              disable: false,
              mozjpeg: {
               progressive: true,
               quality: 65
              },
              // optipng.enabled: false will disable optipng
              optipng: {
               enabled: true,
              },
              pngquant: {
               quality: '65-90',
               speed: 4
              },
              gifsicle: {
               interlaced: false,
              },
              // the webp option will enable WEBP
              webp: {
               quality: 75
              }
            }
          },
        ],
      },
      {
        test: /\.(ttf|otf|eot|woff2?)$/,
        loader: "file-loader",
        options: {
          name: 'fonts/[name].[ext]',
        }
      }
    ],
    noParse: [/\.elm$/]
  },
  optimization: {
    minimizer: [new TerserJSPlugin(), new OptimizeCSSAssetsPlugin({})]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/assets/prod.index.html'
    }),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
})

а вот nginx default.conf

server {
    listen       80;
    server_name  <domain_name>;
    root /usr/share/nginx/html;
    access_log  /var/log/nginx/host.access.log  main;

    index index.html;

    location / {
      try_files $uri $uri/ =404;
    }

    location /images/ {
      alias /usr/share/nginx/html/images/;
      try_files $uri $uri/ =404;
      error_log /var/log/nginx/error.log debug;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

person Eric Steen    schedule 03.10.2019    source источник


Ответы (2)


Для загрузки изображений с помощью url-loader

Если вы заметили, что внутри config/webpack.config.js есть module object, внутри которого есть rules object. Для правил или списка правил предусмотрен ключ ограничения ключ ограничения очень важен

Значение предельного значения — если размер загружаемого изображения превышает указанное предельное значение, то по умолчанию используется загрузчик файлов. например, если у меня конфигурация ниже webpack.config.js

{
  test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
  loader: require.resolve('url-loader'),
  options: {
             limit: 10000,
             name: 'static/media/[name].[hash:8].[ext]',
           },
},

внутри моего moudules -> rules object

Выше предельного значения 10000 байт, поэтому веб-пакет будет загружать только те изображения, используя загрузчик URL, размер которых меньше 10000 байт, если размер изображения равен или больше 10000, то по умолчанию используется загрузчик файлов, пока резервный загрузчик не отключится. указано.

Итак, предположим, что вы динамически добавляете что-то вроде этого в свой код.

import largeimage from '../static/images/largeimage.jpg' или любой другой путь, а размер largeimage меньше предельного значения, изображение не будет загружено.

РЕШЕНИЕ

Чтобы веб-пакет загружал изображение с помощью url-loader, размер вашего большого изображения должен быть меньше предельного значения.

Поэтому либо увеличьте лимит, либо уменьшите размер изображения.

Ссылка https://webpack.js.org/loaders/url-loader/#limit

person Ankit Tiwari    schedule 28.10.2020

url-loader не загружает изображение как отдельный файл, он кодирует файл в формат base64 и включает его в пакет js. Следовательно, не будет отдельного запроса к файлу изображения. См. этот ответ: Url-loader vs File-loader Webpack

Вместо этого попробуйте загрузить изображения с file-loader. Обычно я загружаю и шрифты, и изображения с помощью file-loader, и он работает правильно.

Я использую эту рабочую конфигурацию (разработка):

// this is configured outside of the exported webpack configuration code
const BASE_DIR = resolve(`${__dirname}`);

module.exports = {
    mode: 'development',
    devtool: 'eval-source-map',
    resolve: {
        modules: [
            resolve(BASE_DIR),
            'node_modules'
        ]
    },
    output: {
        // ...
        publicPath: '/'
    },

    module: {
        rules: [
            // ...
            {
                test: /\.(png|svg|jpg|jpeg|gif|tiff)$/,
                use: [
                    'file-loader?name=assets/[name].[ext]'
                ]
            },
            // ...
        ]
    }
    // ...
}

Мой файл изображения физически находится в 'src/assets/logo_arc.png', и я использую его следующим образом:

import logo from 'src/assets/logo_arc.png';
// ...
<img src={logo} alt={'company logo'} />

Я вижу, что мой файл находится в каталоге сборки разработки в подкаталоге assets, как я и ожидал.

При запуске приложения на сервере разработки webopack (на локальном хосте, мой пользовательский порт 9901) изображение обслуживается по адресу http://localhost:9901/assets/logo_arc.png.

В пакете разработки я вижу следующие части:

// definition of webpack public path
/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "/";

// ...

// the image itself as a webpack module
/***/ "./src/assets/logo_arc.png":
/*!*********************************!*\
  !*** ./src/assets/logo_arc.png ***!
  \*********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

eval("module.exports = __webpack_require__.p + \"assets/logo_arc.png\";//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXNzZXRzL2xvZ29fYXJjLnBuZz8wMmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGlCQUFpQixxQkFBdUIiLCJmaWxlIjoiLi9zcmMvYXNzZXRzL2xvZ29fYXJjLnBuZy5qcyIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gX193ZWJwYWNrX3B1YmxpY19wYXRoX18gKyBcImFzc2V0cy9sb2dvX2FyYy5wbmdcIjsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/assets/logo_arc.png\n");

/***/ }),
// importing webpack module into variable, it is used later in the img element
var src_assets_logo_arc_png__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! src/assets/logo_arc.png */ "./src/assets/logo_arc.png");

// ...

// usage in the img element
react__WEBPACK_IMPORTED_MODULE_0__["createElement"]("img", {
        src: src_assets_logo_arc_png__WEBPACK_IMPORTED_MODULE_7___default.a,
        alt: 'company logo'
      }))
person lavor    schedule 03.10.2019
comment
Я пробовал оба много, много раз. Оба, кажется, делают правильные вещи, но по-прежнему не загружают изображения. В URL-адресах есть данные: изображение / jpeg и т. Д., Но все еще только изображения-заполнители Chrome и Safari. - person Eric Steen; 03.10.2019
comment
Как я уже сказал, изображение url-loader преобразуется в формат base64. Замените его на file-loader и найдите имя файла изображения в собранном пакете. Имя файла будет начинаться с пути, это может помочь вам увидеть, что происходит. - person lavor; 03.10.2019
comment
Спасибо за подсказку, но один из моих файлов превышает лимит в 10000, установленный для url-loader, и он тоже не отображается, но есть data:image/jpeg, показывающий, где он должен быть. - person Eric Steen; 03.10.2019
comment
Я последовал вашему совету и искал image/ в app.bundle.js. Я вижу кучу мест с n.p + 'images/image_file.jpeg', и когда я ищу n.p, я вижу n.p=, поэтому он не должен устанавливать n.p? Где webpack берет URL? Кстати это на локалхосте - person Eric Steen; 03.10.2019
comment
np должен быть publicPath веб-пакета (output.publicPath в файле конфигурации веб-пакета). Я вижу его в моем пакете, инициализированном с помощью моего publicPath '/', вы уверены, что вы инициализировали пустой строкой? Webpack не требует знать адрес вашего сервера. Он обслуживает ваши файлы относительно места, где развернут пакет (вы можете немного изменить его с помощью упомянутой опции publicPath). Поэтому вы ничего не можете найти о вашем server_name в комплекте. - person lavor; 04.10.2019
comment
Я отредактировал свой ответ. Я включил все части конфигурации моего веб-пакета, а также информацию из пакета веб-пакетов. Посмотрите на это, если это поможет вам решить вашу проблему. Я предлагаю использовать простой file-loader без image-webpack-loader, пока вы не решите свою проблему. - person lavor; 04.10.2019
comment
Хорошо, посмотрев, я вижу, что получаю два изображения: -rw-r--r-- 1 root root 183K Oct 5 03:29 hero-217ea6c8.jpeg -rw-r--r-- 1 root root 71 Oct 5 03:29 hero.jpeg, а в том, что без хэша, есть это: module.exports = __webpack_public_path__ + "images/hero-217ea6c8.jpeg";, и поэтому оно не отображается. Есть ли способ заставить webpack показывать хешированную версию? - person Eric Steen; 05.10.2019
comment
Спасибо, что направили меня в правильном направлении. Проблема заключалась в хэше в файловом загрузчике, удаление которого, похоже, сработало. - person Eric Steen; 05.10.2019