codesandbox / codesandbox-client

An online IDE for rapid web development
https://codesandbox.io
Other
13.11k stars 2.29k forks source link

global window properties are not loaded when loading an external script #8534

Open yinonby opened 3 months ago

yinonby commented 3 months ago

🐛 bug report

Description of the problem

When loading external script, some global window properties should be added. Specifically, after loading 'mocha' and 'chai' scripts, the following properties should exist: 'window.mocha' and 'window.chai'. This works well in a normal environment. However, when running the same code in a codesandbox, these properties are missing from the global 'window' variable.

It seems that the chai.js and mocha.js script files are downloaded (in the network tab of the browser debugger).

I isolated the problem to the location of 'index.html' file. When it is under the 'src' folder, this problem persists. When it is under the project root folder, this problem doesn't occur.

How has this issue affected you? What are you trying to accomplish?

My goal is to create a codesandbox to demonstrate Mocha capability of running in a browser, as specified here: https://mochajs.org/#running-mocha-in-the-browser

To Reproduce

Create a Node environment with a simple html, sourcing the following script:

Then, in another script, try to access window.chai

In a non-codesandbox environment, you will get a structure. In codesandbox, you will get undefined.

So, when trying to access window.chai.expect, the following Type Error occurs:

Cannot read properties of undefined (reading 'expect')

The reason is that chai is undefined in window

Link to sandbox:

link to sandbox

Your Environment

Software Name/Version
Сodesandbox Latest
Browser Chrome Version 127.0.6533.88 (Official Build) (arm64)
Operating System MacOS Sonoma 14.2.1 (23C71)
CompuIves commented 2 months ago

Hey! Yes, the entry point (index.html) is determined based on the main field in package.json. In this case, the main field is index.html, so it expects to have an entry point of index.html inside the root. I think that's the behaviour, but I have to admit that due to how Parcel is implemented it might also show inconsistent behaviour with order of loading scripts. Our bundler parses the index.html, and then "emits" transpiled files and executes them based on the script tags.

In this case, that should work though. You mention that putting the index.html in the root solves the problem, but I cannot repro that. Could it be that I'm missing something?

yinonby commented 2 months ago

Good point, I reviewed it, and indeed placing the html in the project root, in the sandbox I provided, doesn't solve the issue. It did solve it in my own repository though (another project).

So I isolated it further (in the sandbox I provided), and it seems the <script> tags are simply not running. Take a look at this sandbox It is a simplified project, with practically a basic html, with 2 <div> components, and a <script> in between, which outputs to the console. You will notice that nothing is being output.

Does this make any sense?

CompuIves commented 2 months ago

Ah! That makes sense, there's a discrepancy with our bundler resolving and the one that our static server does. If you open https://d7q7sp.csb.app/index1.html, then you should see that the script tags do work.

The parcel template is a bit hacky, I think that's why we see this behaviour. In this case, the frontend bundler (the one running in the browser) resolves the index1.html because it knows from package.json it needs to resolve this. It does document.write with the contents of the index1.html, but that means that the script tags are not executed.

Meanwhile, our static server does not check package.json to know what file to resolve. Because of this, the file is not served. If the file would be renamed to index.html, then both our bundler and static server would resolve to the same file, meaning that the script tags get executed.

Does that make sense? There are some intricacies from how this was implemented sprinkled around here 😅 .