web-dev-qa-db-fra.com

Webpack, plugin html-webpack, Erreur: échec de la compilation enfant

J'ai un problème avec la configuration de mon webpack. Après avoir implémenté html-webpack-plugin, j'ai eu une erreur, il y a toute la pile d'erreurs générée par index.html.

Pile d'erreurs: plug-in Html Webpack:

 Erreur: échec de la compilation enfant: 
 Conflit: plusieurs actifs émettent vers le même nom de fichier index.html: 
 Erreur: conflit: plusieurs actifs émettent vers le même nom de fichier index.html 
 
  • compiler.js: 76 [Pré-build]/[html-webpack-plugin] /lib/compiler.js:76:16

  • Compiler.js: 291 Compilateur. [Pré-build]/[webpack] /lib/Compiler.js:291:10

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

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

  • CachePlugin.js: 62 Compilateur. [Pré-build]/[webpack] /lib/CachePlugin.js:62:55

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Compilation.js: 448 processModuleDependencies.err [Pré-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


Mon code de configuration de 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'
                }
            },
        }
    };
};

Je n'ai trouvé aucune source de cette erreur, je suis peut-être un peu fatigué, mais j'aimerais terminer, alors j'espère pour votre aide les gars.
Peut-être devrais-je utiliser un peu de raw-loader charger .html (?), ce qui ne me fait pas plaisir.
10
Jakub Chlebowicz

Le problème est en effet le file-loader, car il copie simplement le fichier. Par le temps html-webpack-plugin essaie d'écrire index.html il a déjà été écrit par file-loader, d'où un conflit.

Il existe plusieurs façons de résoudre ce problème, selon vos besoins.

Vous pouvez utiliser html-loader pour votre HTML, bien que si vous vous attendez à ce que votre HTML importé soit simplement copié, ce n'est pas le bon choix. Pour être clair, par le HTML importé, je ne veux pas dire le modèle utilisé par le html-webpack-plugin.

Si vous souhaitez continuer à utiliser le file-loader pour vos autres fichiers HTML, vous pouvez exclure le index.html donc html-webpack-plugin revient à son chargeur par défaut. require.resolve fonctionne comme require mais vous donne le chemin complet du module au lieu de son contenu.

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

Lorsqu'aucun chargeur ne correspond au modèle, le html-webpack-plugin utilise un chargeur ejs comme solution de rechange . Si vous n'avez pas besoin de chargeur pour .html fichiers, vous pouvez supprimer complètement la règle et cela fonctionnera très bien. C'est assez peu probable, sinon vous n'auriez pas de .html règle en premier lieu, mais cela signifie également que vous pouvez utiliser le .ejs extension pour ne pas appliquer le .html règle, car tout le HTML est valide EJS . Vous renommeriez index.html à index.ejs et modifiez la configuration de votre plugin en conséquence:

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