Skip to content

Broken links in Browser.application with prerendered content #105

Open
@ChristophP

Description

@ChristophP

Problem
For SEO reasons as well as to prevent FOUC we prerender our Elm apps with certain tools. That means that by the time the Elm app initializes the DOM is already filled and the Elm app is supposed to "take it from there".
However, links are broken then, in the sense that they will cause a full page reload instead of be intercepted by Browser.application.

Cause

Before Browser.application initializes it seems to call _VirtualDom_virtualize() here in order to hydrate the vdom. Since the content is the same it would render initally the DOM will be left as is. This is problematic because links will not get the same treatment as other links in Browser.application that is happening here

Proposed solution
Add special treatment for links when virtualizing the DOM in this scenario so that clicks on those links will be intercepted as well.

Possible workaround
Whiping the DOM clean before Elm initializes. :-/

SSCCE

<html>
<!-- note the lack of whitespace after the body tag, to make sure no text nodes get inserted by the virtual DOM virtualize function -->
<body><a href="/blog">Prerendered: This link WILL NOT be intercepted by Browser.application</a>
  <script src="/elm.js"></script>
  <script>
    Elm.Main.init()
  </script>
</body>
</html>
module Main exposing (..)

import Browser
import Html exposing (..)
import Html.Attributes exposing (href)

view model =
    Browser.Document "SSCCE"
        [ a [ href "/blog" ] [ text "Prerendered: This link WILL NOT be intercepted by Browser.application" ]
        , br [] []
        , br [] []
        , a [ href "/blog" ] [ text "Dynamically rendered: This link WILL be intercepted by Browser application" ]
        ]

main =
    Browser.application
        { init = \() url key -> ( (), Cmd.none )
        , view = view
        , update = \msg model -> ( model, Cmd.none )
        , subscriptions = \() -> Sub.none
        , onUrlRequest = \urlRequest -> ()
        , onUrlChange = \url -> ()
        }
{
    "type": "application",
    "source-directories": [
        "src"
    ],
    "elm-version": "0.19.1",
    "dependencies": {
        "direct": {
            "elm/browser": "1.0.2",
            "elm/core": "1.0.5",
            "elm/html": "1.0.0"
        },
        "indirect": {
            "elm/json": "1.1.3",
            "elm/time": "1.0.0",
            "elm/url": "1.0.0",
            "elm/virtual-dom": "1.0.2"
        }
    },
    "test-dependencies": {
        "direct": {},
        "indirect": {}
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions