Browser.application cannot share body with other scripts

The issue

Our customers wants us to use third party Cookie consent scripts, such
as Cookie Information, most of these
needs to modify the dom based on some data returned after a network call.

This is fundamentally incompatible with Browser.application which breaks
if DOM elements are added to the <body> by other scripts.

Different versions of this problem have been discussed before here and
here.
The previous OP’s had a problem with browser extensions that randomly edit the DOM, or with third party analytics
extensions that do the same.

What have we tried

We tried patching the generated Js code, so that the elm app is actually initialized
in an element nested inside the body, as suggested in this post. The proposed solution actully seems to work, but patching the generated Js is
obviously a very brittle and unsatisfying solution.

We also considered moving our application to a Browser.element model and handling
the navigation stuff with ports as suggested in this post, but we have a really large application and it would be much more difficult to rely on such a system rather than the build
in Navigation module.

Feature request - allow Browser.application to be started in a node other that body

Because the above “fix” works, it seems it would be easy to just allow the
Browser.application to be started in some other node, like Browser.element.

Is there some reason why this option is not just enabled? It seems like it would
enable many devs to use the Browser.application module in production, where today
they are forced to use Browser.element or patch code etc.

Request for temporary work arounds

Is anyone aware of other approaches that might work?

2 Likes

Looks like you’ve found all past discussions. My read of browser/navigation-in-elements.md at master · elm/browser · GitHub (which you’ve pointed out too) is that it is an intentional tradeoff.

As such, imo the productive way forward, as a user of elm language, is to proceed with wiring up Browser.element. I perform the refactoring on my app once, and didn’t have to be bothered with it anymore. Enjoying the rest of elm :slightly_smiling_face:

1 Like

That is for sure an option, and thanks for the link to your refactoring. A very useful example.

It seems to me that adding the node option to the Browser.application would be an alternative that would fix the problem for at least some cases while allowing us to continue to use the Browser.application package. So I hope to raise a discussion of that option.

1 Like

This is the current work around and your best option.

In Elm 0.18 the application mounted to a given node, this was changed in 0.19 as a way to avoid having extra nesting (and probably with the intention of better support for server side rendering). This was definitely a mistake as it ignored the reality of websites commonly having external scripts/browser extensions that need to add elements to the DOM.

You can create an issue with your specific use case on Issues · elm/browser · GitHub so it can be reviewed next time elm/browser is being worked on. If you’re waiting for an official fix then you’ll probably be waiting for years.

3 Likes

Thank you for your reply. I agree that the removal of the feature seems to have been a mistake.

I will open an issue as you suggest. For now we will rely on the patching but we will explore refactoring to use Browser.element instead as @choonkeat suggests, even if this seems very unfortunate, as the Browser.application is very useful for our SPA.

@jessta may I ask if you currently rely on the patch solution and if you have had any problems with this?

I believe another workaround is to include an empty Html.Keyed node in your Elm view that you can use as the container for the third-party script. If the element’s parents, key, and properties never change, Elm shouldn’t touch it after it initially inserts it.

2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.