javascripthtmlnode.jsecmascript-6webpack-2

Accessing function in bundled javascript (using webpack) from HTML file


I'm currently developing a web application and am in the process of refactoring my code so it's bundled by WebPack.

In my HTML I have a button that calls the sendMessage() function when clicked,

<button type="button" class="btn btn-default" onclick="sendMessage(document.getElementById('claim').value)">Submit</button>

In the first version of my code, the sendMessage() function was defined in a .js file that I imported directly in the HTML,

<script src="my_js/newsArticleScript.js"></script>

The sendMessage() function is directly declared in the file, it's not inside any class or module but it calls other functions defined on the same file, so I don't want to separate it.

But now it's being bundled by WebPack. Here is my config file (the homepageScript.js is for another page):

const path = require('path')

module.exports = {
  entry: {
  	homepage: './src/homepageScript.js',
  	newspage: './src/newsArticleScript.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist/my_js')

  }
}

I changed the script import on the HTML to import the bundled version. And now, when I press the button I get the error

[Error] ReferenceError: Can't find variable: sendMessage

I've read about it, and I learned that webpack does not expose the functions globally. I have tried to export the function, but kept getting the same error.

Can anyone help me with this? Essentially what I need is to understant how to configure webpack or change the JS so it can be accessed by the HTML.

I'm new to JS so I'm pretty sure the way my app is designed is not the best, so any tips on improvements (maybe I should use modules, or there are better ways of calling JS function upon clicking a button) would be welcome as well. Thank you :)


Solution

  • Generally using text-based event handlers isn't a good idea. That said, you have a few options, with increasing amounts of changes.

    1. For texual onchange handlers to work, sendMessage would have to be a global. So the quickest fix would be to change your code to do that. If for instance you have

      function sendMessage(arg){}
      

      in your code, you'd add an additional

      window.sendMessage = sendMessage;
      

      after it to expose it as a global variable.

    2. A more modern approach would be to remove the onchange from the button and have the button labeled with an ID in the HTML, e.g. id="some-button-id".

      Then in your JS code, you could do

      var button = document.querySelector("#some-button-id");
      button.addEventListener("change", function(){
        sendMessage(document.getElementById('claim').value);
      });
      

      to add the change handler function using JS code, instead of with HTML attributes.