问题描述
我的 webpack 配置有问题.实现 html-webpack-plugin 后,我得到了一个错误,生成的 index.html
有整个错误堆栈.
I 've got a problem with my webpack configuration. After implementing html-webpack-plugin I got an Error, there's whole error stack from generated index.html
.
错误堆栈:Html Webpack 插件:
Error Stack:Html Webpack Plugin:
Error: Child compilation failed:
Conflict: Multiple assets emit to the same filename index.html:
Error: Conflict: Multiple assets emit to the same filename index.html
compiler.js:76[预构建]/[html-webpack-plugin]/lib/compiler.js:76:16
compiler.js:76[Pre-build]/[html-webpack-plugin]/lib/compiler.js:76:16
Compiler.js:291 编译器.[预构建]/[webpack]/lib/Compiler.js:291:10
Compiler.js:291 Compiler.[Pre-build]/[webpack]/lib/Compiler.js:291:10
Compiler.js:494[预构建]/[webpack]/lib/Compiler.js:494:13
Compiler.js:494[Pre-build]/[webpack]/lib/Compiler.js:494:13
Tapable.js:138 下一个[预构建]/[tapable]/lib/Tapable.js:138:11
Tapable.js:138 next[Pre-build]/[tapable]/lib/Tapable.js:138:11
CachePlugin.js:62 编译器.[预构建]/[webpack]/lib/CachePlugin.js:62:5
CachePlugin.js:62 Compiler.[Pre-build]/[webpack]/lib/CachePlugin.js:62:5
Tapable.js:142 Compiler.applyPluginsAsyncSeries[预构建]/[tapable]/lib/Tapable.js:142:13
Tapable.js:142 Compiler.applyPluginsAsyncSeries[Pre-build]/[tapable]/lib/Tapable.js:142:13
Compiler.js:491[预构建]/[webpack]/lib/Compiler.js:491:10
Compiler.js:491[Pre-build]/[webpack]/lib/Compiler.js:491:10
Tapable.js:131 Compilation.applyPluginsAsyncSeries[预构建]/[tapable]/lib/Tapable.js:131:46
Tapable.js:131 Compilation.applyPluginsAsyncSeries[Pre-build]/[tapable]/lib/Tapable.js:131:46
Compilation.js:645 self.applyPluginsAsync.err[预构建]/[webpack]/lib/Compilation.js:645:19
Compilation.js:645 self.applyPluginsAsync.err[Pre-build]/[webpack]/lib/Compilation.js:645:19
Tapable.js:131 Compilation.applyPluginsAsyncSeries[预构建]/[tapable]/lib/Tapable.js:131:46
Tapable.js:131 Compilation.applyPluginsAsyncSeries[Pre-build]/[tapable]/lib/Tapable.js:131:46
Compilation.js:636 self.applyPluginsAsync.err[预构建]/[webpack]/lib/Compilation.js:636:11
Compilation.js:636 self.applyPluginsAsync.err[Pre-build]/[webpack]/lib/Compilation.js:636:11
Tapable.js:131 Compilation.applyPluginsAsyncSeries[预构建]/[tapable]/lib/Tapable.js:131:46
Tapable.js:131 Compilation.applyPluginsAsyncSeries[Pre-build]/[tapable]/lib/Tapable.js:131:46
Compilation.js:631 self.applyPluginsAsync.err[预构建]/[webpack]/lib/Compilation.js:631:10
Compilation.js:631 self.applyPluginsAsync.err[Pre-build]/[webpack]/lib/Compilation.js:631:10
Tapable.js:131 Compilation.applyPluginsAsyncSeries[预构建]/[tapable]/lib/Tapable.js:131:46
Tapable.js:131 Compilation.applyPluginsAsyncSeries[Pre-build]/[tapable]/lib/Tapable.js:131:46
Compilation.js:627 sealPart2[预构建]/[webpack]/lib/Compilation.js:627:9
Compilation.js:627 sealPart2[Pre-build]/[webpack]/lib/Compilation.js:627:9
Tapable.js:131 Compilation.applyPluginsAsyncSeries[预构建]/[tapable]/lib/Tapable.js:131:46
Tapable.js:131 Compilation.applyPluginsAsyncSeries[Pre-build]/[tapable]/lib/Tapable.js:131:46
Compilation.js:575 Compilation.seal[预构建]/[webpack]/lib/Compilation.js:575:8
Compilation.js:575 Compilation.seal[Pre-build]/[webpack]/lib/Compilation.js:575:8
Compiler.js:488[预构建]/[webpack]/lib/Compiler.js:488:16
Compiler.js:488[Pre-build]/[webpack]/lib/Compiler.js:488:16
Tapable.js:225[预构建]/[tapable]/lib/Tapable.js:225:11
Tapable.js:225[Pre-build]/[tapable]/lib/Tapable.js:225:11
Compilation.js:477 _addModuleChain[预构建]/[webpack]/lib/Compilation.js:477:11
Compilation.js:477 _addModuleChain[Pre-build]/[webpack]/lib/Compilation.js:477:11
Compilation.js:448 processModuleDependencies.err[预构建]/[webpack]/lib/Compilation.js:448:13
Compilation.js:448 processModuleDependencies.err[Pre-build]/[webpack]/lib/Compilation.js:448:13
next_tick.js:73 _combinedTickCallback内部/进程/next_tick.js:73:7
next_tick.js:73 _combinedTickCallbackinternal/process/next_tick.js:73:7
next_tick.js:104 process._tickCallback内部/进程/next_tick.js:104:9
next_tick.js:104 process._tickCallbackinternal/process/next_tick.js:104:9
我的 webpack 配置代码:
My webpack configuration code:
var webpack = require('webpack'),
path = require('path');
var CopyWebpackPlugin = require('copy-webpack-plugin'),
ExtractTextWebpackPlugin = require('extract-text-webpack-plugin'),
HtmlWebpackPlugin = require('html-webpack-plugin'),
const sourcePath = path.resolve(__dirname, './src');
const staticPath = path.resolve(__dirname, './static');
module.exports = function (env) {
const nodeEnv = env && env.prod ? 'production' : 'development';
const isProd = nodeEnv === 'production';
const postcssLoader = {
loader: 'postcss-loader',
options: {
plugins: function () {
return [
require('autoprefixer')
];
}
}
}
const plugins = [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity,
filename: 'vendor.bundle.js'
}),
new webpack.EnvironmentPlugin({
NODE_ENV: nodeEnv,
}),
new HtmlWebpackPlugin({
template: 'index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
})
];
if(isProd) {
plugins.push(
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
screw_ie8: true,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
if_return: true,
join_vars: true,
},
output: {
comments: false,
},
})
);
} else {
plugins.push(
new webpack.HotModuleReplacementPlugin()
);
}
return {
devtool: isProd? 'source-map' : 'eval',
context: sourcePath,
entry: {
app: './app/entry.ts',
vendor: './app/vendor.ts'
},
output: {
path: staticPath,
filename: '[name].bundle.js',
},
module: {
rules: [
{
test: /\.html$/,
exclude: /node_modules/,
use: {
loader: 'file-loader',
query: {
name: '[name].[ext]'
},
},
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
'ts-loader'
],
},
],
},
resolve: {
alias: {
Public: path.resolve(__dirname,'src/public'),
Style: path.resolve(__dirname,'src/styles')
},
extensions: ['.ts','.js', '.html'],
modules: [
path.resolve(__dirname, 'node_modules'),
sourcePath
]
},
plugins,
performance: isProd && {
maxAssetSize: 100,
maxEntrypointSize: 300,
hints: 'warning'
},
stats: {
colors: {
green: '\u001b[32m'
}
},
devServer: {
contentBase: './src',
historyApiFallback: true,
port: 3000,
compress: isProd,
inline: !isProd,
hot: !isProd,
stats: {
assets: true,
children: false,
chunks: false,
hash: false,
modules: false,
publicPath: false,
timings: true,
version: false,
warnings: true,
color: {
green: '\u001b[32m'
}
},
}
};
};
我找不到那个错误的任何来源,也许我有点累,但我想完成它,所以我希望你们能帮助他们.
I couldn't find any source of that Error, maybe I am little bit tired, but I would like to finish it up, so I hope for your help guys.
也许我应该使用一些 raw-loader
来加载 .html
(?),这让我不高兴.
Maybe should I use some raw-loader
to load .html
(?), which does not make me happy.
推荐答案
问题确实出在 file-loader
上,因为它只是简单地将文件复制过来.当 html-webpack-plugin
尝试编写 index.html
时,它已经由 file-loader
编写,因此导致冲突.
The problem is indeed the file-loader
, because it simply copies the file over. By the time html-webpack-plugin
tries to write index.html
it has already been written by file-loader
, hence resulting in a conflict.
有多种方法可以解决该问题,具体取决于您的需求.
There are several ways to resolve that issue, depending on what your needs are.
您可以将 html-loader
用于您的 HTML,尽管如果您希望简单地复制导入的 HTML,这不是正确的选择.需要明确的是,导入的 HTML 并不是指 html-webpack-plugin
使用的模板.
You could use html-loader
for your HTML, although if you expect your imported HTML to simply be copied, it isn't the correct choice. To be clear, by the imported HTML I don't mean the template used by the html-webpack-plugin
.
如果你想继续为你的其他 HTML 文件使用 file-loader
,你可以排除 index.html
所以 html-webpack-plugin
回退到它的默认加载器.require.resolve
与 require
的工作方式类似,但为您提供模块的完整路径而不是其内容.
If you want to keep using the file-loader
for your other HTML files, you can exclude the index.html
so html-webpack-plugin
falls back to its default loader. require.resolve
works like require
but gives you the full path of the module instead of its content.
{
test: /\.html$/,
exclude: [/node_modules/, require.resolve('./index.html')],
use: {
loader: 'file-loader',
query: {
name: '[name].[ext]'
},
},
},
当没有加载器匹配模板时,html-webpack-plugin
使用 ejs
loader 作为后备.如果您不需要 .html
文件的任何加载程序,您可以完全删除规则,它会工作得很好.这是不太可能的,否则您一开始就不会有 .html
规则,但这也意味着您可以使用 .ejs
扩展名来不应用 .html
规则,因为所有 HTML 都是有效的 EJS.您可以将 index.html
重命名为 index.ejs
并相应地更改您的插件配置:
When no loader matches the template, the html-webpack-plugin
uses an ejs
loader as a fallback. If you don't need any loader for .html
files, you could remove the rule entirely and it would work just fine. That is rather unlikely, otherwise you wouldn't have a .html
rule in the first place, but this also means you can use the .ejs
extension to not apply the .html
rule, as all HTML is valid EJS. You would rename index.html
to index.ejs
and change your plugin configuration accordingly:
new HtmlWebpackPlugin({
template: 'index.ejs',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
})
这篇关于Webpack、html-webpack-plugin、错误:子编译失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!