- From: Carlos Lopez <notifications@github.com>
- Date: Fri, 23 Aug 2019 08:05:39 -0700
- To: whatwg/xhr <xhr@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/xhr/issues/253@github.com>
So, I'm dealing with an issue with bridging older browsers with the new `manifest.json` spec. Due to the way the pages are served, `manifest.json` is served based on certain server criteria (hostname) while `index.html` is a static file from a CDN.
Basically, before the UI events start, and any interaction is possible, I use a `prerender.js` script in <head> to style the document before it's rendered. This could include things like setting different content header padding if the page is rendered on an iOS PWA. Also, I use this pre-render state to set some colors based on `prefers-color-scheme:dark`.
Some properties I want to grab straight from `manifest.json`. This means it has to be intentionally synchronous. For example, let's say I want to style the `background-color` of the document (`<html>`) to be the same as what's in `manifest.json`. Let's say I have the color as `#000` (black). When a PWA loads, it will load a black background, but, if I don't use block the render before changing the `background-color` in `<html>`and, instead do this asynchronously, then the background will flash white (browser default), and then go black.
Here's some short snippets of this configuration:
manifest.json:
````
{
"name": "Full App Name",
"short_name": "App",
"start_url": "/",
"background_color": "#000000",
"display": "standalone",
"theme_color": "#2196F3",
}
````
index.html:
````
<html>
<head>
<link rel="manifest" href="manifest.json" />
<script src="prerender.js">
<!-- Content snip --!>
````
prerender.js
````
import * as Document from '@shortfuse/materialdesignweb/core/document/index';
/** @return {Object} */
function getManifestObject() {
let manifestObject = {};
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
manifestObject = JSON.parse(xhr.responseText);
}
};
xhr.open('GET', 'manifest.json', false);
try {
xhr.send();
} catch (e) {
console.error('Could not load manifest.json');
}
return manifestObject;
}
/**
* @param {!string} name
* @param {string} content
* @return {void}
*/
function setMeta(name, content) {
let attr = document.head.getElementsByTagName('meta').namedItem(name);
if (attr) {
if (content == null) {
attr.parentElement.removeChild(attr);
} else {
attr.setAttribute('content', content);
}
} else if (content != null) {
attr = document.createElement('meta');
attr.setAttribute('content', content);
document.head.appendChild(attr);
}
}
/** @return {void} */
function onDOMContentLoaded() {
const manifest = getManifestObject();
setMeta('apple-mobile-web-app-title', manifest.short_name);
setMeta('apple-mobile-web-app-status-bar-style', manifest.theme_color);
setMeta('theme-color', manifest.theme_color);
document.documentElement.style.setProperty('background-color', manifest.background_color);
document.removeEventListener('DOMContentLoaded', onDOMContentLoaded);
}
Document.onPrerender();
document.addEventListener('DOMContentLoaded', onDOMContentLoaded);
````
I will add, I already have a service worker in place to serve `manifest.json` from cache, so ideally speaking, there's as little load-up time lag as possible here. (I'd imagine first fetch could experience a slight uptick in delay, but I could always add a check to see if the application is running as a PWA before doing the synchronous request.)
Right now, I'm wary about using the synchronous request because of the deprecated nature. The alternative I current have is rewriting the `index.html` file, which complicates the back-end.
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/xhr/issues/253
Received on Friday, 23 August 2019 15:06:02 UTC