go-app icon indicating copy to clipboard operation
go-app copied to clipboard

Give the option to not defer scripts

Open usedbytes opened this issue 3 years ago • 13 comments

I'm really liking the package, thank you for your work!

As noted in #661 app.Handler.Scripts sets defer=true, but this causes problems when components depend on them.

For instance my material components implementation instantiates the Javascript classes in OnMount, but sometimes that gets called before the mdc script has actually loaded.

Putting a non-deferred <script> tag in RawHeaders appears to work OK, but it would be nice to have a way to choose deferred vs non-deferred loading for Scripts somehow.

usedbytes avatar Jun 06 '22 22:06 usedbytes

@usedbytes - I have a go-app material components implementation also if you'd like to take a look at it. Might save you some time in some way.

https://github.com/mlctrez/goapp-mdc
and demo at https://goapp-mdc.mlctrez.com/

Some if not all of the components that I developed make use of auto-init. That may be an option to explore.

mlctrez avatar Jun 06 '22 22:06 mlctrez

@mlctrez Oh neat, thanks for pointing it out! Not sure how I missed yours, I did have a search before I started. Looks like you're further along than me, so I'll see if there's stuff I can contribute to yours instead.

From a very quick look, I think you have the same issue though. Basically this sometimes returns nil in OnMount:

app.Window().Get("mdc")

In particular, if the page is very small (like one component with nothing else), it seems that OnMount manages to run before the parsing of the deferred script; but it's not very deterministic.

usedbytes avatar Jun 07 '22 06:06 usedbytes

@usedbytes A little less than a year later I'm facing the exact issue you're facing.

Honestly crazy this is being enforced; deferring scripts is the stupidest default you could have.

If you had 1 script that is let's say network limited on the host it would keep the rest of the scripts from executing leaving your site crippled. Such a bad design feature.

This is also to the fact of not being able to modify the root body!!! WTF!

c3rtificate avatar Jun 03 '23 19:06 c3rtificate

Well, just add them using the Raw Headers? And what about the body? All I ever needed is possible with: https://github.com/maxence-charriere/go-app/pull/665

oderwat avatar Jun 03 '23 19:06 oderwat

I have this not enforced anymore in the latest feature branch. This will come later but for now, as @oderwat said, you can use raw header for this.

maxence-charriere avatar Jun 03 '23 19:06 maxence-charriere

@oderwat I did end up using the raw headers, I was just stating the oddness of the default in a rather rude way which I apologize for.

What I am referring to in terms of the root body, it's inaccessible from inside of the render. What you referred was inside of the handler struct, which once ran would be static and not changeable unless you would do some crazy workaround changing it using JS.

What I am attempting is changing it inside of the renderer as I use the body for mending between different themes.

Also @maxence-charriere That's awesome news, looking forward to removing 40 or so raw header entries.

c3rtificate avatar Jun 03 '23 19:06 c3rtificate

@c3rtificate well, I have used go-app since the beginning in a way that it never reloads a page from the server. I don't see a problem with just updating attributes of the body tag, but you are right, that can't be done with the renderer.

oderwat avatar Jun 03 '23 20:06 oderwat

@oderwat Thank you for the reply, however how would you realistically update it programmatically without a refresh and without the use of JS interop?

c3rtificate avatar Jun 03 '23 20:06 c3rtificate

I may not understand your problem. I just use DOM manipulation through 'app.Window()' for whatever I need to change in the document.

app.Window().Get("document").Get("body").Get("classList").Call("add", "theme-dark")

oderwat avatar Jun 03 '23 20:06 oderwat

It seems that this would not work for my case as it seems you can only use this approach after the content has been rendered not before it has been sent off to the scheduler to be "rendered"

What I am trying to do is change these things based on conditions before the render actually takes place, your example uses the JS interop interface to change it through that.

Edit: But it's all good, I'll find a work-around either from doing some crazy shenanigans or hope for a future native solution. Thank you for the reply :)

c3rtificate avatar Jun 03 '23 20:06 c3rtificate

Well. I think you need to accept that "Render()" on the objects is called all the time. It does not "render" the page, it updates the nodes of your (many / hierarchical) components.

P.S.: We do not use external JavaScript libraries that change the DOM. It misses the point of using go-app and I believe that will bring many problems when really using go-app to create PWAs. And yes, it is a lot of work to write everything from scratch. But if I would not want to use Go in the frontend, I would just use another (type-script) JavaScript framework. They are pretty mature.

oderwat avatar Jun 03 '23 21:06 oderwat

I am fully aware of these facts. The whole reason why I use go-app is because I despise JS and HTML. My whole point of saying it's JS interop is because it's not doing it through the framework, but rather working around it by accessing the global window and calling JS functions through that tunnel.

c3rtificate avatar Jun 03 '23 21:06 c3rtificate

The "Render()" is also just accessing the DOM and adds HTML elements and attributes, this is how a browser works. You can initialize a canvas and draw everything on that. This is what Flutter does it if not using the DOM variant, you could also use Ebiten, which uses the canvas element. Besides that, everything will always just modify the DOM, HTML and CSS, when you are in the browser.

oderwat avatar Jun 03 '23 21:06 oderwat