Webpack 文件加载器输出 [object Module]
Posted
技术标签:
【中文标题】Webpack 文件加载器输出 [object Module]【英文标题】:Webpack file-loader outputs [object Module] 【发布时间】:2020-03-23 00:15:09 【问题描述】:我正在使用带有 htmlWebpackPlugin
、html-loader
和 file-loader
的 webpack。我有一个简单的项目结构,其中我不使用任何框架,而只使用打字稿。因此,我将我的 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
)
]
;
index.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
编辑 我的 package.json 依赖项:
"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"
【问题讨论】:
【参考方案1】:根据文件加载器docs:
默认情况下,file-loader 生成使用 ES 模块语法的 JS 模块。在某些情况下,使用 ES 模块是有益的,例如在模块连接和摇树的情况下。
似乎 webpack 将 ES 模块 require()
调用解析为如下所示的对象:default: module
,而不是扁平化模块本身。这种行为有些争议,在this issue 中进行了讨论。
因此,要正确解析您的src
属性,您需要能够访问导出模块的default
属性。如果您使用的是框架,您应该能够执行以下操作:
<img src=require('assets/logo.png').default/> <!-- React -->
<!-- OR -->
<img src="require('assets/logo.png').default"/> <!-- Vue -->
或者,您可以启用文件加载器的 CommonJS 模块语法,webpack 将直接解析为模块本身。在你的 webpack 配置中设置 esModule:false
。
webpack.config.js:
test: /\.(png|jpe?g|gif)$/i,
use: [
loader: 'file-loader',
options:
esModule: false,
,
,
],
,
【讨论】:
那行得通。然而,它仍然有点神奇。如果您对为什么会这样有想法,您是否也可以在答案中解释它?谢谢。 @Bora -- 做了更多研究并更新了答案。 在从Angular 8
更新到 Angular 9
的过程中,这让我有点吃惊,因为这将 file-loader
从版本 4.2.0
带到了 6.0.0
。使用require(...).default
为我修复了它。
我在升级文件加载器后遇到了这个问题。仔细查看更新日志,我发现 esModule 的默认值在 5.0.0 版本中更改为 true。
使用 react 16.13.1 我遇到了同样的问题,即 require 不起作用使用 require(...).default 为我修复了它【参考方案2】:
@stellr42 建议在您的 file-loader
配置中修复 esModule: false
是目前最好的解决方法。
然而,这实际上是html-loader
中的一个错误,正在这里跟踪:https://github.com/webpack-contrib/html-loader/issues/203
file-loader
、css-loader
等朋友好像增加了对ES Module的支持,但是漏掉了html-loader
。
修复此错误后,最好删除 esModule: false
并简单升级 html-loader
,因为 ES 模块提供了一些小好处(如 docs 中所述)
或者,如果(像我一样),您发现这个问题是因为您在 从 CSS(而不是从 HTML)加载图像时遇到问题,那么解决方法就是升级 css-loader
,无需禁用 ES 模块。
【讨论】:
【参考方案3】:刚刚将我的文件加载器更新到 ^5.0.2 分钟前。
我知道esModule: false
是建议的修复方法,但这对我不起作用。
我的解决方法是 <img src=require('assets/logo.png').default/>
,这很奇怪。第一次使用.default
,但是成功了。
【讨论】:
【参考方案4】:这发生在文件加载器版本 5.0.2 上,早期版本无需调用 default
属性即可正常工作
【讨论】:
【参考方案5】:而不是这个:<img src="require('assets/logo.png').default"/>
像这样使用它:<img src=require('assets/logo.png').default/>
【讨论】:
【参考方案6】:我在 vuejs 中遇到了同样的问题,esModule:false
对我不起作用。
相反,我使用了@kerubim 解决方案并修复了它,但仅在生产模式和开发模式下我会遇到一些错误。
所以我在util.js
中写了这个函数,解决了我的问题。
maybeDefault: (module) =>
if (typeof module === "object")
module = module.default;
return module;
,
使用示例:
let logo = 'logo.svg';
util.maybeDefault(require(`img/svg/logos/$logo`));
【讨论】:
@Dharman 抱歉,我认为这很清楚,所以是的。我使用了这个功能并解决了我的问题。但在vuejs
,当然也可以用于其他用途。
这在 Gatsby 中为我工作,无需重写 webpack 配置【参考方案7】:
在 react js 中使用 "default" 后跟 require 来显示动态图像
src=require('../images/'+image_name+'.png').default
【讨论】:
【参考方案8】:对于Next.JS:
// require(...).default.src
<img src=require("../public/images/avatar.png").default.src width=256 height=256 />
【讨论】:
【参考方案9】:这是一个奇怪的问题,仍然不确定我的问题是如何解决的。
所以我删除了我的node_module
和package-lock.json
并运行npm install --force
之后效果很好
【讨论】:
以上是关于Webpack 文件加载器输出 [object Module]的主要内容,如果未能解决你的问题,请参考以下文章
Babel Webpack 错误:您可能需要适当的加载器来处理此文件类型