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

Html.Attributes.id "Elm" causes the page to stop loading. #491

Open
MartinSStewart opened this issue Oct 4, 2024 · 8 comments
Open

Html.Attributes.id "Elm" causes the page to stop loading. #491

MartinSStewart opened this issue Oct 4, 2024 · 8 comments

Comments

@MartinSStewart
Copy link

MartinSStewart commented Oct 4, 2024

Steps to reproduce:

  1. Check out this branch https://github.com/MartinSStewart/martins-homepage/tree/weird-bug
  2. Start npx elm-pages dev
  3. Open localhost:1234
  4. You should get this error in the console image

Note that this issue goes away if you go to the previous commit on the branch.

I'm on Windows, Firefox, and I can trigger this error both on Lamdera 1.3 and 1.2.2

@MartinSStewart
Copy link
Author

I've narrowed it down to this

view : App Data ActionData RouteParams -> Shared.Model -> Model -> View (PagesMsg Msg)
view app _ model =
    { title = ""
    , body = Ui.el [ Ui.id "Elm" ] Ui.none
    }

I think what is happening Html.Attribute.id "Elm" is causing some name collision.

@MartinSStewart MartinSStewart changed the title elm-pages dev stops working when I remove an if expression Html.Attributes.id "Elm" causes the page to stop loading. Oct 4, 2024
@MartinSStewart
Copy link
Author

MartinSStewart commented Oct 4, 2024

I've converted Index.elm into a SSCCE for this issue. It's the latest commit on https://github.com/MartinSStewart/martins-homepage/tree/weird-bug

@dillonkearns
Copy link
Owner

Thanks for the issue and SSCCE! I was trying to look through the codebase for anything that references an "elm" or "Elm" HTML id, but couldn't find it 🤔

I also notice that the elm-pages docs site, for example, doesn't have any elements with the ID "elm" or "Elm".

elm-pages - a statically typed site generator 2024-10-07 at 2 28 13 PM

So I'm pretty confused at why this would cause a problem.

@MartinSStewart
Copy link
Author

MartinSStewart commented Oct 9, 2024

The generated JS module name usually is called Elm right? Maybe that can somehow have a name collision with DOM ids?

@lydell
Copy link
Contributor

lydell commented Feb 19, 2025

I ran your SSCCE, and also ran into an error, although not the same as yours.

Uncaught TypeError: cannot use 'in' operator to search for "init" in ""
    findPublicModules http://localhost:1234/elm.js:25173
    _elm_hot_loader_init http://localhost:1234/elm.js:25559
    <anonymous> http://localhost:1234/elm.js:25566
    <anonymous> http://localhost:1234/elm.js:25571

But I can explain why that one happens!

First, you are on the right track that DOM ids can cause conflicts with JS things with the same name. Watch:

Image

The DOM has a feature where if there’s an element on the page with an id attribute which is also a valid JS identifier, a global variable with that name is created, pointing to the element.

In your SSCCE, there’s <div class="s e wf" id="Elm"></div> in the HTML, which then creates a global variable called Elm (a.k.a. window.Elm) which is a reference to that div DOM node.

The script tag for the Elm code has defer:

<script defer src="/elm.js" type="text/javascript"></script>

defer means that the script is guaranteed to run after the whole HTML has been parsed and turned into DOM. So when elm.js runs, the global Elm variable pointing to your div already exists.

Elm supports window.Elm already existing when it runs. It then extends window.Elm with its modules. This allows you to load multiple Elm apps on the same page. This means that Elm assigns Elm.Main in your case, adding a Main property to the div:

Image

Now on to findPublicModules where the error occurred for me. It comes from elm-hot. That code tries to go through everything in Elm to find all the init functions. (In your case, it only needs to find Elm.Main.init but it can’t know the name(s) of your Elm modules.) It expects window.Elm to be a plain JS object, with no other properties than Elm modules. So it tries to do for (var key in parent) { where parent is set to window.Elm, but that also loops through the align property of the div, but window.Elm.align is a string, not an Elm module, so later code then fails.

My guess is that something similar happened when you got the errorJson error. Having id="Elm" seems to be asking for trouble – choose any other name!

If elm-pages really want to solve this, it should be possible. Either by not relying on window.Elm (use a non-global instead), or by going through all the code (including elm-hot) and make sure that it doesn’t expect window.Elm to be “pristine”. But is it worth the trouble?

@MartinSStewart
Copy link
Author

MartinSStewart commented Feb 19, 2025

choose any other name!

Yup, this is what I did.

Thanks for the explanation of what is going wrong. I don't mind having to change id names. The real issue is just that it isn't obvious what to do when this error appears, but given this is probably a very rare bug, maybe it's not worth doing anything about it.

@dillonkearns
Copy link
Owner

Yeah, it is unfortunate. I would consider this more of an Elm thing than an elm-pages thing. Certainly not ideal and I do try to smooth over edges as much as possible, but seems like probably a lot of effort for a pesky little thing so this one is not at the top of my personal to do list. Happy to accept a PR as always though if someone has an elegant fix for this in the future.

@dillonkearns
Copy link
Owner

Either way though, great to have this placeholder and explanation in case anyone else is scratching their heads in the future. So thank you both!

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

3 participants