I have a project which needs to create a dynamic manifest.json file for my PWA (ReactJS).
Please see below my codes:
app.service.js:
function getAppDetails() {
const requestOptions = {
method: 'GET',
headers: authHeader()
};
// TODO create dynamic manifest.json file here
return fetch(`${config.apiUrl}/api/apps`, requestOptions).then(handleResponse);
}
function handleResponse(response) {
return response.text().then(text => {
const data = text && JSON.parse(text);
if (!response.ok) {
if (response.status === 401) {
// auto logout if 401 response returned from api
logout();
location.reload(true);
}
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
return data;
});
}
app.actions.js:
function getAppDetails() {
return dispatch => {
dispatch(request());
appService.getAppDetails()
.then(
details => dispatch(success(details)),
error => dispatch(failure(error.toString()))
);
};
function request() { return { type: appConstants.GETDETAILS_REQUEST } }
function success(details) { return { type: appConstants.GETDETAILS_SUCCESS, details } }
function failure(error) { return { type: appConstants.GETDETAILS_FAILURE, error } }
}
LoginPage.jsx:
import { appActions } from '../_actions';
class LoginPage extends React.Component {
constructor(props) {
super(props);
// reset login status
this.props.dispatch(userActions.logout());
this.state = {
email: '',
password: '',
isDisabled: false,
submitted: false
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.showSwal = this.showSwal.bind(this);
}
componentDidMount() {
// TODO call the action to add dynamic manifest file to index.html
this.props.dispatch(aapActions.getAppDetails());
}
render() {
return (
................
);
}
}
I am new to this kind of thing. How can I get started?
if you want to create dynamic manifest.json you want to have a link tag in the HTML with rel="manifest" but without href attribute. And use this tag later to populate your manifest. As in
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>title</title>
<link rel="manifest" id="my-manifest-placeholder">
</head>
<body>
<!-- page content -->
</body>
</html>
Use a JSON object to set your manifest
var myDynamicManifest = {
"name": "Your Great Site",
"short_name": "Site",
"description": "Something dynamic",
"start_url": "<your-url>",
"background_color": "#000000",
"theme_color": "#0f4a73",
"icons": [{
"src": "whatever.png",
"sizes": "256x256",
"type": "image/png"
}]
}
const stringManifest = JSON.stringify(myDynamicManifest);
const blob = new Blob([stringManifest], {type: 'application/json'});
const manifestURL = URL.createObjectURL(blob);
document.querySelector('#my-manifest-placeholder').setAttribute('href', manifestURL);
Unfortunately, the advice on using blob: or data: URLs fails to work correctly in some cases, because manifest.json URLs are supposed to be static:
Do not change the name or location of your web app manifest file, doing so may prevent the browser from updating your PWA.
As that article explains, there's a special mechanism for updates to manifest.json (triggered by very specific conditions) - it is not supposed to be updated via the URL name.
Moreover, Android may no longer recognize the app as a full (WebAPK-installable) PWA, even when the app passes the Lighthouse check. In that case, it's still "installed" as a regular PWA with an ugly Chrome icon in the corner of the app launch icon. I've spend many hours trying to understand why, and finally stumbled on that article with the explanation.
So please either
manifest.json from a completely static URL, orhref based on some attribute (e.g. hostname) that doesn’t change over the lifetime of the app (so that different variations of manifest could be served for different clients, but each client’s version would have a static URL).If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With