2017-04-19 223 views
2

我的webpack配置有问题。在实现html-webpack-plugin后,我得到一个错误,从生成的index.html有整个错误堆栈。Webpack,html-webpack-plugin,错误:儿童编译失败

错误堆栈: 的Html的WebPack插件:

 
    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 [Pre-build]/[html-webpack-plugin]/lib/compiler.js:76:16

  • Compiler.js:291 Compiler. [Pre-build]/[webpack]/lib/Compiler.js:291:10

  • Compiler.js:494 [Pre-build]/[webpack]/lib/Compiler.js:494:13

  • Tapable.js:138 next [Pre-build]/[tapable]/lib/Tapable.js:138:11

  • CachePlugin.js:62 Compiler. [Pre-build]/[webpack]/lib/CachePlugin.js:62:5

  • Tapable.js:142 Compiler.applyPluginsAsyncSeries [Pre-build]/[tapable]/lib/Tapable.js:142:13

  • Compiler.js:491 [Pre-build]/[webpack]/lib/Compiler.js:491:10

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries [Pre-build]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:645 self.applyPluginsAsync.err [Pre-build]/[webpack]/lib/Compilation.js:645:19

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries [Pre-build]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:636 self.applyPluginsAsync.err [Pre-build]/[webpack]/lib/Compilation.js:636:11

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries [Pre-build]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:631 self.applyPluginsAsync.err [Pre-build]/[webpack]/lib/Compilation.js:631:10

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries [Pre-build]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:627 sealPart2 [Pre-build]/[webpack]/lib/Compilation.js:627:9

  • Tapable.js:131 Compilation.applyPluginsAsyncSeries [Pre-build]/[tapable]/lib/Tapable.js:131:46

  • Compilation.js:575 Compilation.seal [Pre-build]/[webpack]/lib/Compilation.js:575:8

  • Compiler.js:488 [Pre-build]/[webpack]/lib/Compiler.js:488:16

  • Tapable.js:225 [Pre-build]/[tapable]/lib/Tapable.js:225:11

  • Compilation.js:477 _addModuleChain [Pre-build]/[webpack]/lib/Compilation.js:477:11

  • Compilation.js:448 processModuleDependencies.err [Pre-build]/[webpack]/lib/Compilation.js:448:13

  • next_tick.js:73 _combinedTickCallback internal/process/next_tick.js:73:7

  • next_tick.js:104 process._tickCallback internal/process/next_tick.js:104:9

我的WebPack配置代码:

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' 
       } 
      }, 
     } 
    }; 
}; 

我无法找到任何错误来源,也许我有点累了,但我想完成它,所以我希望你的帮助球员。

也许我应该使用一些raw-loader加载.html(?),这并不会让我开心。

回答

4

问题确实是file-loader,因为它只是将文件复制过来。在html-webpack-plugin尝试写入index.html时,它已被写入file-loader,因此导致冲突。

根据您的需求,有几种方法可以解决该问题。

对于HTML,您可以使用html-loader,但如果您希望简单地复制导入的HTML,则不是正确的选择。要清楚,通过导入的HTML我并不是指html-webpack-plugin使用的模板。

如果您想继续使用file-loader作为其他HTML文件,则可以排除index.html,以便html-webpack-plugin可以回退到其默认加载程序。 require.resolve的工作方式与require类似,但会为您提供模块的完整路径而不是其内容。

{ 
    test: /\.html$/, 
    exclude: [/node_modules/, require.resolve('./index.html')], 
    use: { 
     loader: 'file-loader', 
     query: { 
      name: '[name].[ext]' 
     }, 
    }, 
}, 

当没有装载模板匹配,html-webpack-plugin使用一个ejs loader as a fallback。如果您不需要用于.html文件的任何加载程序,则可以完全删除该规则并且它可以正常工作。这是不太可能的,否则您首先不会有.html规则,但这也意味着您可以使用.ejs扩展名来不应用.html规则,因为所有HTML都是有效的EJS。你会重命名index.htmlindex.ejs,并相应地改变你的插件配置:

new HtmlWebpackPlugin({ 
    template: 'index.ejs', 
    minify: { 
     removeComments: true, 
     collapseWhitespace: true, 
     removeAttributeQuotes: true 
    }, 
    chunksSortMode: 'dependency' 
}) 
+0

大答案和解释!我非常感谢你的文章,并且我决定留在'html-webpack-plugin'中,并且删除'html-loader',只要我做单点。真正的感谢,现在对我来说事情更加清晰。 =) –