Yes, what happens is that elm-pages takes the Route Modules that you define and it compiles two versions of your app. One that runs on the Backend (that will execute during your build step, or on the server for server-rendered Routes), and one that runs on the Frontend.
Backend app
- Resolves
datafor the given URL (uses ports under the hood to communicate with NodeJS as needed to read files, etc.) - Takes the resolved Route Module’s
Dataand calls the Route Module’sinit. Throws away theEffect, it only needs theModel - Calls the Route Module’s
viewfunction with theModelfrominitand the resolvedData - Turns the return value of the Route Module’s
viewinto the final HTML to be rendered using theShared.viewfunction, and adding the surrounding HTML for anelm-pagesskeleton (<script>tags,<style>tags, etc.). It also includes a base64 encoded version of the binary encoded version of the Route Module’sData.
Frontend app
- The initial paint of the page is from the HTML (no JS/Elm) that was rendered out on the server as described above
- After the initial paint is all done,
elm-pagespasses in this serializeddatain as an Elm Flag, then renders the Route Module for the given URL. This time,initis called and theEffectis not thrown away but is actually performed. However,datais not performed (it is only ever performed in the Backend, as the nameBackendTaskimplies).datais already available through the Flags thatelm-pagesmanaged under the hood for us. - Any subsequent page navigations will go and reach out to the Backend to resolve the
Datafor that URL. Since the rendered app is a single-page app (SPA), it does not do a full page load (no HTML is downloaded), instead it only downloads the binary serialized form of the Route Module’sData. If it is a pre-rendered Route Module, then this is just loading a static file from a CDN. If it is a server-rendered route, then the server returns that binary content and resolves it at request-time.
Hope that is helpful! Let me know if there’s anything else that’s fuzzy about it. I would love to help demystify these things in the docs, so questions and pointers about which parts are unclear are very helpful!