javascripthtmlwebpackminify

How to keep all functions after webpack build?


Webpack checks the usage of functions and remove (as dead code) the "unused" functions. But if I'm using the function inside HTML, the same function will be removed if none scripts calls it.

For example, I have the script.js:

function doSomething() {
    console.log("clicked button");
}

function explicitUsedFunction() {
    console.log("Hey, function called!");
}

explicitUsedFunction();

And index.html:

<html>
    <head>
        <title>Test</title>
        <script src="script.js"></script>
    </head>
    <body>
        <button onclick="doSomething()">Button</button>
    </body>
</html>

doSomething function is used by onclick button event.

here is my webpack.config.js:

const path = require('path');
const TerserMinimizer = require('terser-webpack-plugin');

module.exports = {
    mode: 'production',
    entry: ["./script.js"],
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    optimization: {
        minimize: true,
        minimizer: [
            new TerserMinimizer({
                terserOptions: {
                    keep_classnames: true,
                    keep_fnames: true
                }
            })
        ]
    }
};

I'm using TerserPlugin to keep function name (because HTML will not be modified). So, the bundle.js file will be:

!function explicitUsedFunction(){console.log("Hey, function called!")}();

doSomething function was removed, the question is, how can I keep all declared functions in bundle.js using Webpack?

Some points about answer need be understood:


Solution

  • After a lot of fights with webpack, I found a simple solution. I need 2 things: send all function to minified file and make event functions acessible on window's scope. I just added the following line for every function I need:

    function doSomething() {
        console.log("clicked button");
    }
    
    function explicitUsedFunction() {
        console.log("Hey, function called!");
    }
    
    explicitUsedFunction();
    
    /*NEW LINE HERE:*/
    window.doSomething = doSomething;
    

    with this simple change I tell to webpack that the function was used and I dont need Terser anymore (webpack.config.js):

    const path = require('path');
    
    module.exports = {
        mode: 'production',
        entry: ["./script.js"],
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'bundle.js'
        }
    };