htmlwebpackhtml-webpack-plugin

Add a script at the end of HTML with HtmlWebpackPlugin


I have a React application with an index.html file in the public folder:

<!DOCTYPE html>
<html lang="ru-RU">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Test</title>
   
    <link rel="dx-theme" data-theme="generic.dark" href="/css/some.css" data-active="false">
    <base href="/" />
</head>

<body class="dx-viewport">
    <div id="root"></div>
    <script src="/scripts/some-script.js"></script>
</body>

</html>

HtmlWebpackPlugin settings:

new HtmlWebpackPlugin({
    favicon: 'public/faviconDOCs.ico',
    template: 'public/index.html',
    scriptLoading: 'blocking',
    minify: {
        removeComments: true,
    },
}),

As a result, Webpack generates the following index.html in the dist folder:

<!DOCTYPE html>
<html lang="ru-RU">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
     <title>Test</title>
   
 <link rel="dx-theme" data-theme="generic.dark" href="/css/some.css" data-active="false">
    <base href="/">
    <link rel="icon" href="/faviconDOCs.ico">
</head>

<body class="dx-viewport">
<div id="root"></div>
 <script src="/scripts/some-script.js"></script>
 <script src="/main.bundle.0cec3d5e983e6fa0c00b.js"></script>
</body>

</html>

But I need the to be included after all the bundled scripts. How can I achieve this?

I tried to add templateParameters with additionalScript

new HtmlWebpackPlugin({
      favicon: 'public/faviconDOCs.ico',
      template: 'public/index.html',
      scriptLoading: 'blocking',
      inject: 'body', // Scripts are added at the end of the body
      minify: {
        removeComments: true,
      },
      templateParameters: {
        additionalScript: '<script src="/tflex-viewer/tflex-viewer3d-widget.js"></script>'
      }
    }),

and html...

<!DOCTYPE html>
<html lang="ru-RU">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Test</title>
   
    <link rel="dx-theme" data-theme="generic.dark" href="/css/some.css" data-active="false">
    <base href="/" />
</head>

<body class="dx-viewport">
    <div id="root"></div>
    <%= additionalScript %> 
</body>

</html>

But the output is the same

<body class="dx-viewport">
<div id="root"></div>
<script src="/scripts/some-script.js"></script>
<script src="/main.bundle.0cec3d5e983e6fa0c00b.js"></script>
</body>

How can I make the script be included at the end of all scripts in index.html?

Thank you in advance.


Solution

  • By specifying the order of scripts in the HTML template, we can achieve the desired result.

    <!DOCTYPE html>
    <html lang="ru-RU">
    
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Test</title>
    
        <link rel="dx-theme" data-theme="generic.dark" href="/css/some.css" data-active="false">
        <base href="/" />
    </head>
    
    <body class="dx-viewport">
        <div id="root"></div>
        <!-- Insert all Webpack scripts -->
        <%= htmlWebpackPlugin.tags.bodyTags %>
        <!-- Add the additional script after all bundled scripts -->
        <%= htmlWebpackPlugin.options.templateParameters.additionalScript %>
    </body>
    
    </html>
    

    And for the plugin, we set inject: false to disable automatic script insertion:

    new HtmlWebpackPlugin({
        favicon: 'public/faviconDOCs.ico',
        template: 'public/index.html',
        inject: false,
        scriptLoading: 'blocking',
        minify: {
            removeComments: true,
        },
        templateParameters: {
            additionalScript: '<script src="/tflex-viewer/tflex-viewer3d-widget.js"></script>'
        }
    }),
    

    Now, the output will be as expected - Webpack will generate the following index.html:

    <!DOCTYPE html>
    <html lang="ru-RU">
    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <title>T-FLEX DOCs</title>
       <link rel="dx-theme" data-theme="generic.dark" href="/css/some.css" data-active="false">
    </head>
    
    <body class="dx-viewport">
        <div id="root"></div>
    
        <script src="/main.bundle.950a4151bb8f16528cf1.js"></script>
    
        <script src="/script/script-test.js"></script>
    </body>
    
    </html>
    

    As a result, the required script (script-test.js) is included at the end (As required by the task conditions)