html-webpack-plugin multiple entry points adding all scripts
Asked Answered
C

2

11

I'm building a project on an ejected react cli. The reason I ejected it is because there will be multiple pages being generated and some stand alone scripts that I wanted to make and have them take advantage of the ES6 and debugging tools provided by the boilerplate.

My problem is that while using the technique to build out multiple pages with html-webpack-plugin builds out the generated HTML files with both scripts from each page.

So, lets have a look at the basic entry point

Here's my basic web pack config.

...
entry: {

      devServerClient : require.resolve('react-dev-utils/webpackHotDevClient'),
      // Finally, this is your app's code:
      ...pages,

    },
...

As you can see, I'm using the same hot module reloading stuff that came with the boiler plate, but then I deviate to spread in values from the pages variable which is being required from another page:

const glob = require("glob");
const path = require("path");

const input_path = path.resolve(__dirname, "../src/apps/*/index.js");
const apps_directories = glob.sync(input_path);

let pages = {};

// Loop through them and append them to the pages object for processing.
apps_directories.map(function (app_directory) {
    const split_name = app_directory.split("/");
    pages[split_name[split_name.length - 2]] = app_directory;
});

module.exports = pages;

Thats how I generate multiple entries dynamically. This portion of the code works fine, but I thought I'd post it just in case something needs to happen here that I'm missing.

Next We have the actual plugin section. I take a similar approach in modularizing the code, so here's that portion in the config (root level of the web pack object):

...
plugins: [
    // Generates an `index.html` file with the <script> injected.
    ...HtmlWebpackPlugins,
    ...
]
...

Again, I spread them in, the script that generates these looks like so:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const pages = require("./multiplePaths");
const paths = require("./paths");

const NODE_ENV = process.env.NODE_ENV;

let HtmlWebpackPlugins = [];

Object.keys(pages).map(function (fileName) {
    if (NODE_ENV === "development") {
        HtmlWebpackPlugins.push( new HtmlWebpackPlugin({
            inject: true,
            template: paths.appHtml,
            filename: `${fileName}.html`,
        }));
        return;
    }

    HtmlWebpackPlugins.push(new HtmlWebpackPlugin({
        inject: true,
        template: paths.appHtml,
        filename:  `${fileName}.html`,
        minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeRedundantAttributes: true,
            useShortDoctype: true,
            removeEmptyAttributes: true,
            removeStyleLinkTypeAttributes: true,
            keepClosingSlash: true,
            minifyJS: true,
            minifyCSS: true,
            minifyURLs: true,
        },
    }));
});

module.exports = HtmlWebpackPlugins;

This script here generates the multiple instances of the HtmlWebpackPlugin class per entry, and we also name the html file based on the folder the name of the folder the app resides in. This satisfies the technique in their issues section.

The problem then happens in the generated HTML page. Notice that the scripts for all the folders are injected in each app:

enter image description here

As you can see, each app's CSS and JS are added. This happens to both pages. I only want the relevant CSS and JS to each page.

Any idea what's going on here?

Conformation answered 17/10, 2018 at 0:13 Comment(0)
S
16

If you want to add only some of the chunks inside each page you need to specify which chunks exactly you want to have inside your html as scripts:

HtmlWebpackPlugins.push(new HtmlWebpackPlugin({
    inject: true,
    template: paths.appHtml,
    filename:  `${fileName}.html`,
    chunks: [filename], // add any chunks you need here (for example, chunk with libraries
    ....
});
Scapular answered 17/10, 2018 at 0:33 Comment(1)
Wow, this fixed it. Thank you!Conformation
N
1

I used something like this to create entries for HtmlWebpackPlugin based on webpack entries:

// Webpack entries
const entry = {
  "nameA": "./xy/nameA/main.js",
  "nameB": "./xy/nameB/main.js",
};

// Plugins
let plugins = [];

// HTML injection
Object.keys(entry).forEach((ent) => {
    const htmlPlugin = new HtmlWebpackPlugin({
      inject: true,
      title: "Your Title",
      template: "./html/index.html",
      filename: `formats/${ent}/index.html`,
      chunks: [ent],
    });
    plugins.push(htmlPlugin);
});

// Insert more plugins
plugins = plugins.concat([
    ... your plugins
]);

// Return Config
return {
  // define entry point
  entry,

  // define output file
  output: {
      ...
  },

  ...

  // define Plugins
  plugins,
  
  ...
  
  };
Natalee answered 8/9, 2021 at 19:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.