Skip to content

Commit

Permalink
Merge pull request #48 from dillonkearns/fix-missing-content-flash
Browse files Browse the repository at this point in the history
Fix missing content flash
  • Loading branch information
dillonkearns committed Jan 21, 2020
2 parents acbf631 + 838b7c0 commit 446f114
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 37 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG-ELM.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [1.1.2] - 2020-01-20

### Fixed
- "Missing content" message no longer flashes between pre-rendered HTML and the Elm app hydrating and taking over the page. See [#48](https://github.com/dillonkearns/elm-pages/pull/48).

## [1.1.1] - 2020-01-04

### Fixed
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG-NPM.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [1.1.8] - 2020-01-20

### Fixed
- "Missing content" message no longer flashes between pre-rendered HTML and the Elm app hydrating and taking over the page. See [#48](https://github.com/dillonkearns/elm-pages/pull/48).

## [1.1.7] - 2020-01-12

### Fixed
Expand Down
5 changes: 5 additions & 0 deletions generator/src/develop.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const webpack = require("webpack");
const middleware = require("webpack-dev-middleware");
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");
const PrerenderSPAPlugin = require("prerender-spa-plugin");
const merge = require("webpack-merge");
Expand Down Expand Up @@ -159,6 +160,10 @@ function webpackOptions(
inject: "head",
template: path.resolve(__dirname, "template.html")
}),
new ScriptExtHtmlWebpackPlugin({
preload: /\.js$/,
defaultAttribute: 'defer'
}),
new FaviconsWebpackPlugin({
logo: path.resolve(process.cwd(), `./${manifestConfig.sourceIcon}`),
favicons: {
Expand Down
2 changes: 1 addition & 1 deletion generator/src/template.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="preload" href="content.json" as="fetch" crossorigin />
<link rel="preload" href="./content.json" as="fetch" crossorigin />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
Expand Down
20 changes: 19 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ module.exports = function pagesInit(
let prefetchedPages = [window.location.pathname];

document.addEventListener("DOMContentLoaded", function() {
httpGet(`${window.location.origin}${window.location.pathname}/content.json`, function (/** @type JSON */ contentJson) {

let app = mainElmModule.init({
flags: {
secrets: null
secrets: null,
isPrerendering: navigator.userAgent.indexOf("Headless") >= 0,
contentJson
}
});

Expand All @@ -33,6 +37,9 @@ module.exports = function pagesInit(

document.dispatchEvent(new Event("prerender-trigger"));
});

})

});

function setupLinkPrefetching() {
Expand Down Expand Up @@ -130,3 +137,14 @@ module.exports = function pagesInit(
document.getElementsByTagName("head")[0].appendChild(meta);
}
};

function httpGet(/** @type string */ theUrl, /** @type Function */ callback)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(JSON.parse(xmlHttp.responseText));
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"node-sass": "^4.12.0",
"prerender-spa-plugin": "^3.4.0",
"sass-loader": "^8.0.0",
"script-ext-html-webpack-plugin": "^2.1.4",
"style-loader": "^1.0.0",
"webpack": "^4.41.5",
"webpack-dev-middleware": "^3.7.0",
Expand Down
74 changes: 42 additions & 32 deletions src/Pages/ContentCache.elm
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,10 @@ pagesWithErrors cache =
init :
Document metadata view
-> Content
-> Maybe { contentJson : ContentJson String, initialUrl : Url }
-> ContentCache metadata view
init document content =
parseMetadata document content
init document content maybeInitialPageContent =
parseMetadata maybeInitialPageContent document content
|> List.map
(\tuple ->
Tuple.mapSecond
Expand Down Expand Up @@ -149,39 +150,48 @@ createBuildError path decodeError =


parseMetadata :
Document metadata view
Maybe { contentJson : ContentJson String, initialUrl : Url }
-> Document metadata view
-> List ( List String, { extension : String, frontMatter : String, body : Maybe String } )
-> List ( List String, Result String (Entry metadata view) )
parseMetadata document content =
parseMetadata maybeInitialPageContent document content =
content
|> List.map
(Tuple.mapSecond
(\{ frontMatter, extension, body } ->
let
maybeDocumentEntry =
Document.get extension document
in
case maybeDocumentEntry of
Just documentEntry ->
frontMatter
|> documentEntry.frontmatterParser
|> Result.map
(\metadata ->
-- TODO do I need to handle this case?
-- case body of
-- Just presentBody ->
-- Parsed metadata
-- { body = parseContent extension presentBody document
-- , staticData = ""
-- }
--
-- Nothing ->
NeedContent extension metadata
)
(\( path, { frontMatter, extension, body } ) ->
let
maybeDocumentEntry =
Document.get extension document
in
case maybeDocumentEntry of
Just documentEntry ->
frontMatter
|> documentEntry.frontmatterParser
|> Result.map
(\metadata ->
let
renderer =
\value ->
parseContent extension value document
in
case maybeInitialPageContent of
Just { contentJson, initialUrl } ->
if initialUrl.path == ("/" ++ String.join "/" path) then
Parsed metadata
{ body = renderer contentJson.body
, staticData = contentJson.staticData
}

else
NeedContent extension metadata

Nothing ->
NeedContent extension metadata
)
|> Tuple.pair path

Nothing ->
Err ("Could not find extension '" ++ extension ++ "'")
)
Nothing ->
Err ("Could not find extension '" ++ extension ++ "'")
|> Tuple.pair path
)


Expand Down Expand Up @@ -327,8 +337,8 @@ lazyLoad document url cacheResult =
|> Task.map
(\downloadedContent ->
update cacheResult
(\thing ->
parseContent extension thing document
(\value ->
parseContent extension value document
)
url
downloadedContent
Expand Down
53 changes: 51 additions & 2 deletions src/Pages/Internal/Platform.elm
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@ type alias Flags =
Decode.Value


type alias ContentJson =
{ body : String
, staticData : Dict String String
}


init :
pathKey
-> String
Expand Down Expand Up @@ -249,11 +255,33 @@ init :
init pathKey canonicalSiteUrl document toJsPort viewFn content initUserModel flags url key =
let
contentCache =
ContentCache.init document content
ContentCache.init document content (Maybe.map (\cj -> { contentJson = cj, initialUrl = url }) contentJson)

contentJson =
flags
|> Decode.decodeValue (Decode.field "contentJson" contentJsonDecoder)
|> Result.toMaybe

contentJsonDecoder : Decode.Decoder ContentJson
contentJsonDecoder =
Decode.map2 ContentJson
(Decode.field "body" Decode.string)
(Decode.field "staticData" (Decode.dict Decode.string))
in
case contentCache of
Ok okCache ->
let
phase =
case Decode.decodeValue (Decode.field "isPrerendering" Decode.bool) flags of
Ok True ->
Prerender

Ok False ->
Client

Err _ ->
Client

( userModel, userCmd ) =
initUserModel maybePagePath

Expand Down Expand Up @@ -284,6 +312,7 @@ init pathKey canonicalSiteUrl document toJsPort viewFn content initUserModel fla
, url = url
, userModel = userModel
, contentCache = contentCache
, phase = phase
}
, cmd
)
Expand All @@ -297,6 +326,7 @@ init pathKey canonicalSiteUrl document toJsPort viewFn content initUserModel fla
, url = url
, userModel = userModel
, contentCache = contentCache
, phase = Client
}
, Cmd.batch
[ userCmd |> Cmd.map UserMsg
Expand Down Expand Up @@ -333,9 +363,15 @@ type alias ModelDetails userModel metadata view =
, url : Url.Url
, contentCache : ContentCache metadata view
, userModel : userModel
, phase : Phase
}


type Phase
= Prerender
| Client


update :
String
->
Expand Down Expand Up @@ -524,7 +560,20 @@ application config =
\msg outerModel ->
case outerModel of
Model model ->
update config.canonicalSiteUrl config.view config.pathKey config.onPageChange config.toJsPort config.document config.update msg model
let
userUpdate =
case model.phase of
Prerender ->
noOpUpdate

Client ->
config.update

noOpUpdate =
\userMsg userModel ->
( userModel, Cmd.none )
in
update config.canonicalSiteUrl config.view config.pathKey config.onPageChange config.toJsPort config.document userUpdate msg model
|> Tuple.mapFirst Model
|> Tuple.mapSecond (Cmd.map AppMsg)

Expand Down
2 changes: 1 addition & 1 deletion src/Pages/Internal/Platform/Cli.elm
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ cliApplication :
cliApplication cliMsgConstructor narrowMsg toModel fromModel config =
let
contentCache =
ContentCache.init config.document config.content
ContentCache.init config.document config.content Nothing

siteMetadata =
contentCache
Expand Down

0 comments on commit 446f114

Please sign in to comment.