Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible Bug: Parcel is commenting out my JS #5378

Closed
john01dav opened this issue Nov 22, 2020 · 6 comments
Closed

Possible Bug: Parcel is commenting out my JS #5378

john01dav opened this issue Nov 22, 2020 · 6 comments

Comments

@john01dav
Copy link

🐛 bug report

This is related to this, so a misunderstanding on my part is possible, but it appears to be a bug since there is an HTML file that is valid by itself but fails when compiled through Parcel. When I have the following HTML file as source:

<html>
<head>
<!-- The same thing happens if the script is referenced via <script src="… -->
<script>
function myFunction(){
  alert("An alert.");
}
//window.myFunction = myFunction; //If this is absent, then an error takes place. If this is present, then no error takes place
</script>
</head>
<body>
<button onclick="myFunction()">Show an alert</button> <!-- Error: myfunction() doesn't exist outside the module -->
</body>
</html>

I get errors in the JS console and, more importantly, no alert on the screen, when I click on the button. The fact that the commented-out window.myFunction line is able to fix the issue suggests that the script is functioning as a module, despite not being marked as such in the source code and nothing in the documentation specifying how, exactly, that works. Furthermore, if it were a module, then imports of other modules in my code would work from that script tag, and they do not (see the linked discussion for more detail);

🎛 Configuration (.babelrc, package.json, cli command)

An MCVE is attached which shows all configuration. The parcel version is specified in package.json and pacakge-lock.json, so build it like this:

npm install
npm run build # this will, I think, use the exact version of parcel that I'm using

🤔 Expected Behavior

I expect an alert to appear

😯 Current Behavior

An error appears in the JS console and there is no alert.

💁 Possible Solution

The only workaround I know of is the window.… line in my example.

🔦 Context

Without being able to import modules or access code in modules from onclick handlers, I'm forced to put every shared function in the window object, which is obviously problematic for code organization purposes.

💻 Code Sample

See attached

🌍 Your Environment

Software Version(s)
Parcel See package-lock.json and package.json, it is the latest version as of a few minutes beforet his issue report. I'm not quite sure how to read package-lock.json, so I regretfully can't be of more help on this point.
Node 15.2.1
npm/Yarn npm 6.14.8
Operating System Arch Linux, updated earlier today

Download the MCVE here

@john01dav
Copy link
Author

john01dav commented Nov 22, 2020

It's relatively clear why the error happens when I look at the generated/output index.html in dist, but it isn't clear what to do about it (to me):

<html><head><script>
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJtYXBwaW5ncyI6IiIsInNvdXJjZXMiOltdLCJzb3VyY2VzQ29udGVudCI6W10sIm5hbWVzIjpbXSwidmVyc2lvbiI6MywiZmlsZSI6InBhcmNlbC1idWcuSEFTSF9SRUZfZTkxM2NiYmQ5ODZlM2NmYzBhZDc3ODFlMjAzYWFlNzEuanMubWFwIn0=
</script></head><body> <button onclick="myFunction()">Show an alert</button>  </body></html>

@john01dav
Copy link
Author

@devongovett @DeMoorJasper I'm pinging you both since it looks like you're active contributors and it seems like my issue may not be getting seen because I did a previous reply, which, in the issue list, makes it look like a reply has already happened from a maintainer when it has, in fact, not. I'm not sure if you care about this, but I would like to mention that I'm feeling like I'm forced to switch away from Parcel due to this issue and the associated discussion (which has also not gotten any reply) to something that's more maintained — I realize that this tool is free, but if you want it to be used for more than hobby projects, then prompt responses to questions and bug reports is essential.

@devongovett
Copy link
Member

We will of course take a look, but do keep in mind that it's been less than 24 hours since you opened your issue, and it's a weekend. 😄

@john01dav
Copy link
Author

john01dav commented Nov 22, 2020

We will of course take a look, but do keep in mind that it's been less than 24 hours since you opened your issue, and it's a weekend. smile

Thanks for taking a look! I probably came off a bit harsh, so I apologies ­— I mostly just wanted to make sure that it was on the radar, due to the comment issue.

@devongovett
Copy link
Member

So, I think you got the general idea of what's happening in your discussion post. Parcel treats all JS as modules, meaning top-level variables are scoped to the module and are not global. To access them from event handler attributes in HTML, you'll need to do as you suggested and assign the values to the global scope manually. In normal browser javascript without parcel, this happens implicitly, but Parcel always wraps each module in its own scope.

If you'd like to avoid global variables, implicit or not, it's generally best to assign event handlers like this instead:

<html>
<head>
<!-- The same thing happens if the script is referenced via <script src="… -->
<script>
function myFunction(){
  alert("An alert.");
}

let button = document.getElementById('button');
button.onclick = myFunction;
</script>
</head>
<body>
<button id="button">Show an alert</button>
</body>
</html>

We are considering changing the behavior here a bit to be closer to native browser JavaScript, however. Ideally, Parcel would simply take in standard HTML and JS, and make it more optimized, without changing the semantics. That's not currently the case here, so thanks for opening this issue.

I will also reply on your other discussion post to help explain some of the other things you saw.

@john01dav
Copy link
Author

So, I think you got the general idea of what's happening in your discussion post. Parcel treats all JS as modules, meaning top-level variables are scoped to the module and are not global. To access them from event handler attributes in HTML, you'll need to do as you suggested and assign the values to the global scope manually. In normal browser javascript without parcel, this happens implicitly, but Parcel always wraps each module in its own scope.

If you'd like to avoid global variables, implicit or not, it's generally best to assign event handlers like this instead:

<html>
<head>
<!-- The same thing happens if the script is referenced via <script src="… -->
<script>
function myFunction(){
  alert("An alert.");
}

let button = document.getElementById('button');
button.onclick = myFunction;
</script>
</head>
<body>
<button id="button">Show an alert</button>
</body>
</html>

We are considering changing the behavior here a bit to be closer to native browser JavaScript, however. Ideally, Parcel would simply take in standard HTML and JS, and make it more optimized, without changing the semantics. That's not currently the case here, so thanks for opening this issue.

I will also reply on your other discussion post to help explain some of the other things you saw.

Thank you for your help! This makes perfect sense, now that it's cleanly laid out like this. I'd like to suggest adding your reply here mostly word-for-word to the documentation, as I think that it would really help new users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants