Webpack 文件加载器输出[对象模块]

我使用与 HtmlWebpackPluginhtml-loaderfile-loader网络包。我有一个简单的项目结构,不使用框架,只使用打印脚本。因此,我将我的 HTML 代码直接写到 index.html。在 HtmlWebpackPlugin中,我还使用这个 HTML 文件作为模板。

正如所有的网站,我需要把一个图像,这是指一个 PNG 在我的资产文件夹。file-loader应该正确地加载文件,将新的文件名放在 src标记中,但这不是正在发生的事情。相反,作为 src标记的值,我使用的是 [object Module]。我假设 file-loader发出一些对象,当它的 .toString()方法运行时,它是这样表示的。但是,我可以看到 file-loader已经成功地处理了该文件,并以新的名称发出到输出路径。没有错误。这是我的 webpack 配置和 index.html

const projectRoot = path.resolve(__dirname, '..');


{
entry: path.resolve(projectRoot, 'src', 'app.ts'),
mode: 'production',
output: {
path: path.resolve(projectRoot, 'dist'),
filename: 'app.bundle.js'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.html$/i,
use: 'html-loader'
},
{
test: /\.(eot|ttf|woff|woff2|svg|png)$/i,
use: 'file-loader'
},
{
test: /\.scss$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: false
}
},
{
loader: 'css-loader',
options: {
sourceMap: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}
]
},
{
exclude: /node_modules/,
test: /\.ts$/,
use: 'ts-loader'
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(projectRoot, 'src', 'index.html')
}),
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css',
ignoreOrder: false
})
]
};

.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
</head>
<body class="dark">
<header>
<nav class="navigation">
<div class="left">
<img src="assets/logo.png" class="logo"> <!-- This logo is output as [object Module] -->
</div>
<div class="right">


</div>
</nav>
</header>
</body>
</html>

项目结构:

config/
webpack.config.js
dist/
src/
styles/
assets/
logo.png
index.html
app.ts

剪辑 返回文章页面我的包译者:

"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.2.0",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"ts-loader": "^6.2.1",
"typescript": "^3.7.2",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
49831 次浏览

Per the file-loader docs:

By default, file-loader generates JS modules that use the ES modules syntax. There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.

It seems that webpack resolves ES module require() calls to an object that looks like this: {default: module}, instead of to the flattened module itself. This behavior is somewhat controversial and is discussed in this issue.

Therefore, to get your src attribute to resolve correctly, you need to be able to access the default property of the exported module. If you're using a framework, you should be able to do something like this:

<img src={require('assets/logo.png').default}/> <!-- React -->
<!-- OR -->
<img src="require('assets/logo.png').default"/> <!-- Vue -->

Alternatively, you can enable file-loader's CommonJS module syntax, which webpack will resolve directly to the module itself. Set esModule:false in your webpack config.

webpack.config.js:

 {
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
esModule: false,
},
},
],
},

This happens on file-loader version 5.0.2 , earlier version works fine without calling default property

@stellr42's suggested fix of esModule: false in your file-loader configuration is the best workaround at the current time.

However, this is actually a bug in html-loader which is being tracked here: https://github.com/webpack-contrib/html-loader/issues/203

It looks like ES Module support was added to file-loader, css-loader, and other friends, but html-loader was missed.

Once this bug is fixed, it will be better to remove esModule: false and simply upgrade html-loader, as ES Modules offer some minor benefits (as mentioned in the docs)

Alternatively, if (like me), you found this issue because you were having trouble loading an image from CSS (instead of from HTML), then the fix is just to upgrade css-loader, no need to disable ES Modules.

Just updated my file-loader to ^5.0.2 minutes ago.

I know esModule: false was the suggested fix but that did not work for me.

My fix was <img src={require('assets/logo.png').default}/> which was weird. First time using .default but it worked.

Instead of this: <img src="require('assets/logo.png').default"/>

Use it like this: <img src={require('assets/logo.png').default}/>

I had the same problem in vuejs and esModule:false did not work for me. Instead, I used @kerubim solution and it fixed it, but only in production mode and in development mode I get some error.

So I wrote this function in util.js that solved my problem.

maybeDefault: (module) => {


if (typeof module === "object") {


module = module.default;
}


return module;
},

use example:

let logo = 'logo.svg';
util.maybeDefault(require(`img/svg/logos/${logo}`));

Use "default" followed by require to display a dynamic image in react js

src={require('../images/'+image_name+'.png').default}

For Next.JS:

// require(...).default.src
<img src={require("../public/images/avatar.png").default.src} width={256} height={256} />


This is a weird issue still unsure how mine got fixed.

So I deleted my node_module and package-lock.json and ran npm install --force

and it worked fine after

I have had the same problem recently after upgrading Laravel Mix v4 to v6. This works fine with me in my Vue component.

<img :src="require('./assets/profile.png').default"/>