问题描述
使用webpack5进行图片资源打包时,打包后图片打不开,并且有重复的图片资源。
问题分析
1、webpack.config.js配置文件代码:
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "built.js",
path: resolve(__dirname, "build")
},
module: {
rules: [
// loader配置
{
test: /\.less$/,
// 使用多个loader用use
use: [
"style-loader",
"css-loader",
"less-loader"
]
}, {
// 处理图片资源
test: /\.(jpg|png|gif)$/,
// 只用一个loader时就直接用loader
// 需要下载url-loader file-loader
loader: "url-loader",
// loader配置
options: {
// 当图片大小小于8kb,就会被base64处理
// base64优点:减少请求数量(减轻服务器压力)
// base64缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024
}
}
]
},
plugins: [
// 插件配置
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: "development"
}
发现配置文件没有问题,打包时图片使用了url-loader和file-loader。考虑是不是这两个loader的问题。
到webpack官网查看资料以后,发现官方这样描述:
当在 webpack 5 中使用旧的 assets loader(如 file-loader/url-loader/raw-loader 等)和 asset 模块时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为 ‘javascript/auto’ 来解决。
所以我们在webpack5使用这些loader时需要添加:
type: 'javascript/auto'
这样以后再使用webpack打包,查看打包后效果:
发现资源里面是[object%20Module]
这里发现url-loader默认采用ES模块语法,即import ‘…/example.png’;
然而Vue生成的是CommonJS模块语法,即require(’…/example.png’);二者不一致。
要么让file-loader或url-loader采用CommonJS语法,要么让Vue采用ES语法。
我们需要让loader使用CommonJS语法,所以需要在loader配置中添加
esModule: false
最后,webpack5图片资源打包成功。完整代码如下:
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "built.js",
path: resolve(__dirname, "build")
},
module: {
rules: [
// loader配置
{
test: /\.less$/,
// 使用多个loader用use
use: [
"style-loader",
"css-loader",
"less-loader"
]
}, {
// 处理图片资源
test: /\.(jpg|png|gif)$/,
// 只用一个loader时就直接用loader
// 需要下载url-loader file-loader
loader: "url-loader",
// loader配置
options: {
// 当图片大小小于8kb,就会被base64处理
// base64优点:减少请求数量(减轻服务器压力)
// base64缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
esModule: false
},
type: "javascript/auto"
}
]
},
plugins: [
// 插件配置
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: "development"
}