如何让Webpack正确处理图片?解决图片转字体及原图片丢失问题
我帮你分析一下问题所在,这是典型的Webpack loader规则冲突导致的,接下来给你拆解问题并提供修复方案:
问题根源
你的Webpack配置里存在重复的文件类型匹配规则,再加上规则执行顺序的影响,导致图片被错误处理:
- 你写了两个规则都匹配了
png和svg:一个用file-loader+image-webpack-loader处理图片,另一个用url-loader处理字体,但错误地把图片格式也包含了进去。 - Webpack会按
rules数组的顺序匹配文件,当svg或小体积png被第二个规则命中时,会被当作字体文件处理,于是生成了奇怪的.eot/.ttf文件;而超过url-loaderlimit的图片又被两个规则重复处理,最终导致原png文件“丢失”。 - 另外还有个小问题:你把
jshint-loader(JS代码检查工具)放在了CSS处理链里,这完全没用还可能引发错误。
修正后的完整配置
const path = require('path'); // 必须引入path模块,原配置漏了这行! const ExtractTextPlugin = require('extract-text-webpack-plugin'); // 确保你安装了这个插件 module.exports = (env) => { const isProduction = env === 'production'; const CSSExtract = new ExtractTextPlugin('styles.css'); return { entry: ['babel-polyfill', './src/app.js'], output: { path: path.resolve(__dirname, "./public/scripts"), filename: 'bundle.js' }, module: { rules: [{ loader: 'babel-loader', test: /\.js$/, exclude: /node_modules/ }, { // 仅处理图片类型:png/jpg/svg test: /\.(png|jp(e*)g|svg)$/, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'assets/', // 修正publicPath:输出目录在public/scripts,所以图片引用路径要回退到上级目录 publicPath: '../assets/' } }, { loader: 'image-webpack-loader', options: { optipng: { optimizationLevel: 7 }, pngquant: { quality: '65-90' }, mozjpeg: { quality: 65 } } }] }, { test: /\.s?css$/, use: CSSExtract.extract({ use : [ { loader : 'css-loader', options : { sourceMap : true } }, { loader : 'sass-loader', options : { sourceMap : true } } // 移除错误的jshint-loader ] }) }, { // 仅处理字体类型:彻底移除png/svg,避免冲突 test: /\.(woff|woff2|eot|ttf)$/, loader: 'url-loader?limit=100000' }] }, plugins : [ CSSExtract, ], devtool: isProduction ? 'source-map' : 'cheap-eval-source-map', devServer: { contentBase: path.join(__dirname, "public"), publicPath: "/scripts/", historyApiFallback: true }, } }
关键修复点说明
- 拆分匹配规则:把图片和字体的处理规则完全分开,确保每种文件类型只被对应的loader处理,从根源避免冲突。
- 修正图片引用路径:因为你的输出目录是
public/scripts,图片输出到public/assets,所以file-loader的publicPath设为../assets/,保证bundle里的图片引用路径正确。 - 移除无效loader:删掉CSS处理链里的
jshint-loader,它只对JS文件有用。 - 补全依赖引入:添加
path模块的引入,否则path.resolve会报错。
额外建议
- 如果你的项目里同时有普通图片svg和字体图标svg,可以给它们单独写规则区分,比如通过目录匹配:
// 处理普通图片svg { test: /\.svg$/, exclude: /src/icons/, // 排除图标目录 use: [/* 图片loader配置 */] }, // 处理字体图标svg { test: /\.svg$/, include: /src/icons/, // 仅处理图标目录 use: [/* 字体loader配置 */] } - 修复前先清空
public/scripts/assets和public/assets目录,避免旧的错误文件干扰。
内容的提问来源于stack exchange,提问作者turisap
相关产品推荐
相关产品推荐

