Webpack url-loader 或 file-loader 不工作反应应用程序
Webpack url-loader or file-loader not working react app
使用带有 url-loader 或 file-loader 的 Webpack 4,图像无法在浏览器中加载。小图像不在数据中 url(或者如果它们是浏览器则不显示它们)并且文件网络请求不是使用文件加载器进行的。
Nginx 在 https://{server}/images/image_name.png
正确提供图像,但在 https://{server}
没有提供图像,并且没有在网络检查器网络面板中进行图像网络调用。
到目前为止最好的猜测是 Webpack url-loader 或 file-loader 不能正确生成 URL。在 app.bundle.js 中搜索 url 时找不到主机。几天来,我已经尝试了 publicPath
、outputPath
等所有其他 Whosebug 帖子的每种组合,但没有任何效果。
除了搜索js,还有什么方法可以查看webpack生成的url吗? webpack 配置不对?故障排除建议?
以下是我在代码中处理图像的方式:
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;
}
}
url-loader
不是将图像作为单独的文件加载,而是将文件编码为 base64 格式并将其包含到 js 包中。因此,将不会单独请求图像文件。看到这个答案:
尝试使用 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'
}))
使用url-loader
加载图像
如果你注意到里面 config/webpack.config.js
有一个 module object
里面有 rules object
。
对于提供的规则或规则列表,有限制键
限制键很重要
限值意义
- 如果要加载的图像大小大于提供的限制值,则默认使用 file-loader。
例如
如果我有以下 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字节
因此 webpack 将仅加载那些使用 url-loader 且大小小于 10000 字节的图像,如果发现图像大小等于或大于 10000,则默认使用 file-loader 直到未指定回退加载程序。
假设您要在代码中动态添加类似这样的图像。
import largeimage from '../static/images/largeimage.jpg'
或任何路径
并且 largeimage
的大小小于限制值图像将不会被加载。
解决方案
为了使 webpack 使用 url-loader 加载图像,您的大图像尺寸应小于限制值。
所以要么增加限制,要么减小图像的大小。
使用带有 url-loader 或 file-loader 的 Webpack 4,图像无法在浏览器中加载。小图像不在数据中 url(或者如果它们是浏览器则不显示它们)并且文件网络请求不是使用文件加载器进行的。
Nginx 在 https://{server}/images/image_name.png
正确提供图像,但在 https://{server}
没有提供图像,并且没有在网络检查器网络面板中进行图像网络调用。
到目前为止最好的猜测是 Webpack url-loader 或 file-loader 不能正确生成 URL。在 app.bundle.js 中搜索 url 时找不到主机。几天来,我已经尝试了 publicPath
、outputPath
等所有其他 Whosebug 帖子的每种组合,但没有任何效果。
除了搜索js,还有什么方法可以查看webpack生成的url吗? webpack 配置不对?故障排除建议?
以下是我在代码中处理图像的方式:
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;
}
}
url-loader
不是将图像作为单独的文件加载,而是将文件编码为 base64 格式并将其包含到 js 包中。因此,将不会单独请求图像文件。看到这个答案:
尝试使用 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'
}))
使用url-loader
加载图像如果你注意到里面 config/webpack.config.js
有一个 module object
里面有 rules object
。
对于提供的规则或规则列表,有限制键
限制键很重要
限值意义
- 如果要加载的图像大小大于提供的限制值,则默认使用 file-loader。
例如
如果我有以下 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字节 因此 webpack 将仅加载那些使用 url-loader 且大小小于 10000 字节的图像,如果发现图像大小等于或大于 10000,则默认使用 file-loader 直到未指定回退加载程序。
假设您要在代码中动态添加类似这样的图像。
import largeimage from '../static/images/largeimage.jpg'
或任何路径
并且 largeimage
的大小小于限制值图像将不会被加载。
解决方案
为了使 webpack 使用 url-loader 加载图像,您的大图像尺寸应小于限制值。
所以要么增加限制,要么减小图像的大小。