7

I have created a functionality using static variablevariables in manifest.json such as :

 -- name
 -- short_name
 -- start_url

And it's working fine for the "Add To Home Screen". When I set manifest.json variable dynamically, the add to screen does not work

Basically I have an e-commerce PWA. My requirement is the following: if a user visits the app url (ex: www.example.com/products/PRODUCT_NAME_A ), he should be able to create a shortcut link on home screen or many they want based on different URLs.

You can also check my code that I have done so far in javascript:



var domain = document.location.origin;
var currentUrl = window. location. href;

var myDynamicManifest = {
    "name": "My App",
    "short_name": "My App",
    "description": "This is my App",
    "start_url": currentUrl,
    "scope": ".",
    "background_color": "#5F6EDD",
    "theme_color": "#efbc4b",
    "orientation": "portrait",
    "display": "standalone",
    "lang": "en",
    "dir": "ltr",
    "icons": [
        {
          "src"     : domain + "/images/logo/logo_70x70.png",
          "sizes"   : "70x70",
          "type"    : "image/png"
        },
        {
          "src"     : domain + "/images/logo/logo_120x120.png",
          "sizes"   : "120x120",
          "type"    : "image/png"
        },
        {
          "src"     : domain + "/images/logo/logo_144x144.png",
          "sizes"   : "144x144",
          "type"    : "image/png"
        },

    ]
    }

const stringManifest = JSON.stringify(myDynamicManifest);

const blob = new Blob([stringManifest], {type: 'application/javascript'});

const manifestURL = URL.createObjectURL(blob);

document.querySelector('#manifest').setAttribute('href', manifestURL);

I expected the output being like: http://prntscr.com/oej48u

1 Answers1

12

I realize this is an old question. But, I thought I'd pass along how I addressed the issue. My front end is served via Netlify and the back-end API is all GCP Cloud Functions. I added a Cloud Function that responds to /manifest?startUrl=...&name=... and returns the right manifest.json contents. Then, in the single page app, it dynamically updates the header <link /> to point to the appropriate URL when the page loads or the user navigates around.

client side:

const manifest = document.getElementById('manifest');
const nextManifest = document.createElement('link');
nextManifest.id = 'manifest';
nextManifest.rel = 'manifest';
nextManifest.href =
  `https://<cloud function host>/manifest?startUrl=${
    encodeURIComponent(`/events/${token}`)
  }&name=${encodeURIComponent(event.name)}`;
manifest.parentNode.replaceChild(nextManifest, manifest);

server side:


const manifest = {
  "short_name": "Photo Feed",
  "name": "Photo Feed",
  "icons": [
    {
      "src": "shortcut-icon.png",
      "sizes": "16x16",
      "type": "image/png"
    },
    {
      "src": "mobile-app-icon.png",
      "sizes": "180x180",
      "type": "image/png"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#591A0C",
  "background_color": "#06B8B3"
};

/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
exports.manifest = (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');

  if (req.method === 'OPTIONS') {
    res.set('Access-Control-Allow-Methods', 'GET');
    res.set('Access-Control-Allow-Headers', 'Content-Type');
    res.set('Access-Control-Max-Age', '3600');
    res.status(204).send('');
    return;
  }

  if (req.method === 'GET') {
    // take /?startUrl=<url> and return a manifest file
    // with `star_url`, same with name
    if (req.query.startUrl) {
      res.json({
        ...manifest,
        short_name: req.query.name || manifest.short_name,
        name: req.query.name ? `${req.query.name} Photo Feed` : manifest.name,
        start_url: req.query.startUrl,
      });
    } else {
      res.json(manifest);
    }
  }

  res.status(405).send();
};
  • This was my solution too, but unfortunately I'm finding it unreliable. The browser has its own logic for when a fresh manifest file is required, and it seems that is not necessarily on every route change. It means that the user can end up installing an outdated manifest. Still looking at solutions. – defraggled Apr 07 '21 at 14:31
  • Did you ever find a more reliable solution? – Ka Tech Jun 08 '21 at 22:38
  • Btw please see [https://web.dev/manifest-updates/](https://web.dev/manifest-updates/) for an explanation of the logic for `manifest.json` updates. And unfortunately, other solutions involving `blob:` and `data:` URLs don't work reliably either, because `manifest.json` URL is supposed to be static, as explained there. – dan Feb 24 '22 at 02:06