jantimon/html-webpack-plugin

Control the order at which scripts are presented in template and executed

ackvf opened this issue · 2 comments

ackvf commented

Context:
I am developing a JIRA plugin app that relies on some window objects that I am mocking in another bundle.

Problem:
The requested window.AJS object is being called from the main bundle before the mock is executed (100ms later).
image

I need to be able to inject the mock bundle first and make it finish processing sooner than the main app bundle.

Solution:

  • I don't really mind if both are defer as long as they are executed in correct order.
    -> solution: respect order of chunks
  • Acceptable solution would also be to use blocking with the mock bundle and defer with the main bundle.
    -> solution: allow separate scriptLoading configuration for each chunk. e.g.:
    scriptLoading?: "blocking" | "defer" | "module" | undefined | Record<string, "blocking" | "defer" | "module" | undefined>
    scriptLoading: {
      index_head: 'blocking',
      index: 'defer',
    }
    

Order of chunks defined in options do not affect the order at which they are presented in the template.
image image

ackvf commented

Okay, please disregard this. The order at which the bundles are injected is controlled by entry field of Webpack config.

image

image

@ackvf

you can try to use new html-bundler-webpack-plugin to have full control for all scripts and styles used in a HTML template.

Specify source scripts and styles directly in HTML where you need:

<html>
<head>
  <!-- load source style -->
  <link href="./style.scss" rel="stylesheet">
  <!-- load source script -->
  <script src="./mocks/AJS.ts" defer="defer"></script>
</head>
<body>
  <h1>Hello World!</h1>
  <!-- load source script -->
  <script src="./index.tsx"></script>
</body>
</html>

The generated HTML:

<html>
<head>
  <link href="css/style.05e4dd86.css" rel="stylesheet">
  <script src="js/AJS.f4b855d8.js" defer="defer"></script>
</head>
<body>
  <h1>Hello World!</h1>
  <script src="js/index.5d8f4b85.js"></script>
</body>
</html>

Webpack config

const path = require('path');
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlBundlerPlugin({
      entry: {
        // define HTML templates here
        index: 'src/views/home/index.html', // output dist/index.html
      },
      js: {
        // output filename of extracted JS from source script loaded in HTML via `<script>` tag
        filename: 'js/[name].[contenthash:8].js',
      },
      css: {
        // output filename of extracted CSS from source style loaded in HTML via `<link>` tag
        filename: 'css/[name].[contenthash:8].css',
      },
    }),
  ],
  module: {
    rules: [
      {
        test: /.html/,
        loader: HtmlBundlerPlugin.loader, // HTML template loader
      },
      // ... other rules, e.g. for TypeScript, SCSS, images, fonts, etc.
    ],
  },
};