Search code examples
webpackhtml-webpack-plugin

HtmlWebpackPlugin can't find index.html, but outputs its error into the index.html it claims to not find


I'm trying to convert our entire build from requirejs and a mess to webpack, so I'll do my best to keep only the relevant details below.

The error, output in console from webpack

ERROR in   Error: Child compilation failed:
  Entry module not found: Error: Can't resolve '/home/user/Documents/ide/dist/index.html' in '/home/user/Documents/ide':
  Error: Can't resolve '/home/user/Documents/ide/dist/index.html' in '/home/user/Documents/ide'

The same error, output in /home/user/Documents/ide/dist/index.html

Html Webpack Plugin:<pre>
  Error: Child compilation failed:
  Entry module not found: Error: Can't resolve '/home/user/Documents/ide/dist/index.html' in '/home/user/Documents/html':
  Error: Can't resolve '/home/user/Documents/ide/dist/index.html' in '/home/user/Documents/ide'

Under webpack config's plugins

new HtmlWebpackPlugin({
            filename: config.build.index,
            template: 'dist/index.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
            },

I have confirmed that config.build.index evaluates to /home/user/Documents/ide/dist/index.html

I don't understand, I thought the html file was generated by this plugin, why am I getting errors in the very file it can't find?

Other resources suggesting changing index.html to index.ejs, this did nothing. I have also tried an absolute path, this didn't work.

Just in case, my configs (mostly stolen from the vue-webpack cli builder):

My base config:

module.exports = {
    context: path.resolve(__dirname, '../'),
    entry: {
        app: './public/js/ide.js'
    },
    output: {
        path: config.build.assetsRoot,
        filename: '[name].js',
        publicPath: process.env.NODE_ENV === 'production'
            ? config.build.assetsPublicPath
            : config.dev.assetsPublicPath
    },
    resolve: {
        extensions: ['.js', '.vue', '.json'],
        alias: {
            '@': resolve('public/js'),
        },
        modules: ['node_modules']
    },
    module: {
        rules: [
            ...(config.dev.useEslint ? [createLintingRule()] : []),
            {
                test: /\.js$/,
                loader: 'babel-loader',
                include: [resolve('public/js'), resolve('test')]
            },
            { test: /\.hbs$/, loader: "handlebars-loader" },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: utils.assetsPath('img/[name].[hash:7].[ext]')
                }
            },
            {
                test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: utils.assetsPath('media/[name].[hash:7].[ext]')
                }
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
                }
            }
        ]
    },
    node: {

        setImmediate: false,
        dgram: 'empty',
        fs: 'empty',
        net: 'empty',
        tls: 'empty',
        child_process: 'empty'
    }
};

Which merges with the production config I'm trying to get to work:

const webpackConfig = merge(baseWebpackConfig, {
    module: {
        rules: utils.styleLoaders({
            sourceMap: config.build.productionSourceMap,
            extract: true,
            usePostCSS: true
        })
    },
    devtool: config.build.productionSourceMap ? config.build.devtool : false,
    output: {
        path: config.build.assetsRoot,
        filename: utils.assetsPath('js/[name].[chunkhash].js'),
        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env': env
        }),
        new UglifyJsPlugin({
            uglifyOptions: {
                compress: {
                    warnings: false
                }
            },
            sourceMap: config.build.productionSourceMap,
            parallel: true
        }),
        new ExtractTextPlugin({
            filename: utils.assetsPath('css/[name].[contenthash].css'),
            allChunks: false,
        }),
        new OptimizeCSSPlugin({
            cssProcessorOptions: config.build.productionSourceMap
                ? { safe: true, map: { inline: false } }
                : { safe: true }
        }),
        new HtmlWebpackPlugin({
            filename: process.env.NODE_ENV === 'testing'
                ? 'index.html'
                : config.build.index,
            template: 'dist/index.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
            },
            chunksSortMode: 'dependency'
        }),
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        }),
        new webpack.HashedModuleIdsPlugin(),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks(module) {
                return (
                    module.resource &&
                    /\.js$/.test(module.resource) &&
                    module.resource.indexOf(
                        path.join(__dirname, '../node_modules')
                    ) === 0
                )
            }
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'manifest',
            minChunks: Infinity
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'app',
            async: 'vendor-async',
            children: true,
            minChunks: 3
        }),
        new CopyWebpackPlugin([
            {
                from: path.resolve(__dirname, '../static'),
                to: config.build.assetsSubDirectory,
                ignore: ['.*']
            }
        ])
    ]
});

Solution

  • template refers to a template html file which you offer to the plugin instead of the output path. The plugin will then inject bundle script information to the bottom of the template.