Practically, your main issue is you're not actually serving the javascript file from your server in any way. A bigger potential issue, though, is that you're not clear on the difference between server-side and client-side code. So, I'm going to try to explain what's happening in your two examples, and what you should do, rather than just how to get this to work.
What's going on when you drag the HTML file directly into the browser?
Please note I am guessing on a lot of these file paths.
In this case, there is no server, so there's only one javascript engine running — Chromium's.
When you drag /home/pi/buttonHtml.html
into your browser, the browser shows a URI of file:///home/pi/buttonHtml.html
. When this script is loaded
<script type = "text/javascript" src="/home/pi/htmlFile.js"></script>
it loads the javascript from file:///home/pi/htmlFile.js
, which is the javascript file that you wrote, and has myFunction
in it.
Generally, URIs that start with /
keep the thing before the ://
, and any domain name or IP address that follows it, and just replace everything after the next /
.
What's going on when you run the javascript file?
When you run the file /home/pi/htmlFile.js
as a server (presumably with node /home/pi/htmlFile.js
or something like it), there are now two javascript engines running — Node's and Chromium's. These do not touch each other at all. This can be confusing since they are both JavaScript, but that's just for convenience and doesn't actually connect them. Imagine you wrote the server in another language. If the backend was written in C, you wouldn't expect the webpage to be able to do onclick="malloc(4)"
.
So what actually ends up happening?
Initially, Node runs your htmlFile.js
file. This creates the myFunction
function in Node (not in Chromium), as well as reading in buttonHtml.html
and listening on a port.
Now, when you open http://192.168.1.115:8000
, Chromium sends a request to Node, and Node sends the contents of buttonHtml.html
back to Chromium, which Chromium shows as a webpage.
On the webpage, you have this:
<script type = "text/javascript" src="/home/pi/htmlFile.js"></script>
Since the webpage is now at http://192.168.1.115:8000
, it decides "/home/pi/htmlFile.js"
means to send a request to http://192.168.1.115:8000/home/pi/htmlFile.js
. This sends a second request to the Node server.
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end(indexFile);
This code here does not check what file we're asking the Node server for. No matter what, it sends indexFile
, which has the contents of buttonHtml.html
in it. So the script tag now tries to load buttonHtml.html
as javascript, which obviously doesn't work, causing Unexpected token: '<'
error.
When we try to call myFunction()
from Chromium, it can't find the function. That's because the function only exists in Node, and Chromium hasn't seen it before.
What if we fix the server to properly serve htmlFile.js
This might fix your problem with myFunction()
not working, but it will be weird and cause other issues. For example:
const http = require("http");
When you run this on the server in Node, it works how you expect. However, if you run this in Chromium, it will say Uncaught ReferenceError: require is not defined
. This is because Node is different than Chromium. The both run JavaScript, and they're similar, but they aren't the same thing.
What should we do instead?
Instead, you should have two javascript files (or two groups of javascript files, as they grow) — ones for the client, and ones for the server. Don't try to send your whole backend code to the client, since they aren't the same thing.
Once you've made a separate javascript file with myFunction
in it, you'll need to get your server to properly serve this file. I won't include a tutorial here — there's a hundred different ways to, and you already seem to know how to serve a file, generally.
You can check the javascript is being served properly by going to http://192.168.1.115:8000/wherever/you/decide/to/serve/it.js
and seeing all your javascript (and nothing but your javascript). Then you can load it on the webpage properly with your script tag.
But I need to share data between the server and the client!
If you do this:
let value = "lorem";
function serverFunction() {
value = "ipsum";
}
function clientFunction() {
console.log(value);
}
and you call serverFunction()
on the server, then clientFunction()
on the client, it will log "lorem"
. The server and the client are running completely separate instances of JavaScript and have two completely separate value
variables. If you need to send data from the client to the server (or vice versa), you need encode the data & send an HTTP request (or communicate in some other way). The client does not have direct access to the server's code in any way.
So, when you say:
Please note I don't want to use inline javascript because the main .js will communicate on other interface that provides some important data.
I expect you'll run into the problem you're worried about here whether you use inline javascript or not.
Summary
You can fix this issue by making sure the server properly servers htmlFile.js
, but your confusion regarding client vs. server-side javascript is likely to cause you bigger issues, so you should split those up too.