本文介绍了Webpack 文件加载器输出 [目标模块]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在使用带有 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, '..');{条目:path.resolve(projectRoot, 'src', 'app.ts'),模式:'生产',输出: {路径:path.resolve(projectRoot, 'dist'),文件名:'app.bundle.js'},解决: {扩展名:['.ts', '.js']},模块: {规则: [{测试:/.html$/i,使用:'html-loader'},{测试:/.(eot|ttf|woff|woff2|svg|png)$/i,使用:'文件加载器'},{测试:/.scss$/i,利用: [{加载器:MiniCssExtractPlugin.loader,选项: {hmr:假的}},{加载器:'css-加载器',选项: {源地图:假}},{loader: 'sass-loader',选项: {源地图:假}}]},{排除:/node_modules/,测试:/.ts$/,使用:'ts-loader'}]},插件: [新的 CleanWebpackPlugin(),新的 HtmlWebpackPlugin({模板:path.resolve(projectRoot, 'src', 'index.html')}),新的 MiniCssExtractPlugin({文件名: '[name].[hash].css',chunkFilename: '[id].[hash].css',忽略顺序:假})]};
index.html:
<html lang="zh-cn"><头><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title></title><body class="dark"><nav class="导航"><div class="left"><img src="assets/logo.png" class="logo"><!-- 这个标志作为[对象模块]输出-->
<div class="right">
</nav></标题>
项目结构:
config/webpack.config.js距离/来源/款式/资产/标志.png索引.html应用程序
编辑我的 package.json 依赖项:
"clean-webpack-plugin": "^3.0.0","css-loader": "^3.2.0","文件加载器": "^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","打字稿": "^3.7.2","webpack": "^4.41.2","webpack-cli": "^3.3.10","webpack-dev-server": "^3.9.0"
解决方案
根据文件加载器 文档:
默认情况下,file-loader 生成使用 ES 模块语法的 JS 模块.在某些情况下,使用 ES 模块是有益的,例如模块串联和摇树的情况.
似乎 webpack 将 ES 模块的 require()
调用解析为如下所示的对象:{default: module}
,而不是扁平模块本身.这种行为有些争议,在这个问题中进行了讨论.
因此,要让您的 src
属性正确解析,您需要能够访问导出模块的 default
属性.如果您使用的是框架,则应该能够执行以下操作:
<!-- 反应 --><!-- 或 --><img src="require('assets/logo.png').default"/><!-- Vue -->
或者,您可以启用文件加载器的 CommonJS 模块语法,webpack 将直接解析为模块本身.在你的 webpack 配置中设置 esModule:false
.
webpack.config.js:
{测试:/.(png|jpe?g|gif)$/i,利用: [{加载器:'文件加载器',选项: {esModule:假,},},],},
I am using webpack with HtmlWebpackPlugin
, html-loader
and file-loader
. I have a simple project structure in which I use no frameworks, but only typescript. Thus, I write my HTML code directly to index.html
. I also use this HTML file as my template in HtmlWebpackPlugin
.
As all websites do I need to put an image which refers to a PNG in my assets folder. file-loader
should load the file correctly put the new filename inside the src
tag but that is not what is happening. Instead, as the value of src
tag, I have [object Module]
. I assume the file-loader
emits some object and it is represented like this when its .toString()
method is run. However, I can see that file-loader
has processed the file successfully and emitted with new name to the output path. I get no errors. Here is my webpack configuration and 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>
Project structure:
config/
webpack.config.js
dist/
src/
styles/
assets/
logo.png
index.html
app.ts
EditMy package.json dependencies:
"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"
解决方案
Per the file-loader docs:
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,
},
},
],
},
这篇关于Webpack 文件加载器输出 [目标模块]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!