如何在PWA中使用动态清单文件?

3
我们有一个SaaS平台,需要根据用户设置加载不同的清单文件。一旦应用程序启动并获取了用户设置,我想要加载正确的清单文件。然而,这并没有起作用。我尝试了几种不同的方法,但无法触发beforeinstallprompt事件。
如果我在我的index.html中加载一个清单文件,然后不更改清单文件的href,似乎每次都可以正常工作。
我尝试在index.html中在清单元素上保留空的href,然后稍后更新它,但是当我这样做时,beforeinstallprompt未被触发。
在我的index.html中:
<link rel="manifest" href="">

或者
<link rel="manifest" href="/manifest.json">

在我的Bootstrap JS文件中,一旦我确定要加载哪个清单文件,就可以更新href到清单。
var href = "https://xxx.s3.eu-central-1.amazonaws.com/sites/1/manifest2.json";
var manifestJson = {
  "name": "test in code",
  "short_name": "test in code",
  "icons": [
    {
      "src": "https://xxx.s3.eu-central-1.amazonaws.com/sites/0/icons/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "https://xxx.s3.eu-central-1.amazonaws.com/sites/0/icons/android-chrome-256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "https://xxx.s3.eu-central-1.amazonaws.com/sites/0/icons/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "start_url": "http://localhost:9000/home/",
  "display": "standalone",
  "background_color": "#2B3D4B",
  "theme_color": "#00afec",
  "prefer_related_applications": false
};
var stringManifest = JSON.stringify(manifestJson);
var blob = new Blob([stringManifest], {type: 'application/json'});
var manifestURL = URL.createObjectURL(blob);

// I have tried both ways of updating the manifest below

// $("head").find("link[rel='manifest']").attr("href", manifestURL);
$("head").find("link[rel='manifest']").attr("href", href);

window.addEventListener('beforeinstallprompt', function(event) {
    console.log("poa: \nxxxxxxxxxx BEFOREINSTALLPROMPT xxxxxxxxxxx\n\n");
    $("body").addClass("hypo-install-prompt");

    // Save the event for later use (when the user clicks an install button)
    app.cache.beforeinstallprompt = event;
});

navigator.serviceWorker.getRegistrations().then(function(registrations) {
    console.log("Unregister ServiceWorker", registrations);
    for (var i = 0; i < registrations.length; i++) {
       var registration = registrations[i];
       registration.unregister();
    }
});

navigator.serviceWorker.register('/home/serviceWorker.js', { scope: '/home/' }).then(function(registration) {
   // Registration was successful
   console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
   console.log('ServiceWorker registration failed: ', err);
});

我知道这是一个相当常见的情况,很多人已经解决了它,但目前为止没有任何一种方法适用于我。有人有什么提示吗?


我知道这是一个相当常见的情况,许多人已经解决了它 - 是吗?你能展示一个已经解决了这个“相当常见情况”的PWA的例子吗?(显然不是代码,而是你知道的已经解决了这个问题的PWA) - Jaromanda X
1
@JaromandaX 是的,我认为这是“相当”普遍的问题,因为我发现了许多关于此问题的帖子/文章。然而,由于某种原因,它们都对我无效。 - poa
1个回答

2

根据您获取用户设置的方式,您可以将您的数据URI动态编写成WebManifest,这样在页面加载时正确的WebManifest已经被引用,不需要单独获取:

<link rel="manifest" href='data:application/manifest+json,{"name": "test in code", "short_name": "test in code", "icons": [{"src": "https://xxx.s3.eu-central-1.amazonaws.com/sites/0/icons/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png"}, {"src": "https://xxx.s3.eu-central-1.amazonaws.com/sites/0/icons/android-chrome-256x256.png", "sizes": "256x256", "type": "image/png"}, {"src": "https://xxx.s3.eu-central-1.amazonaws.com/sites/0/icons/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png"}], "start_url": "http://localhost:9000/home/", "display": "standalone", "background_color": "#2B3D4B", "theme_color": "#00afec", "prefer_related_applications": false}' />

1
嗯,但这正是我试图解决的问题。如果我没有在你的回答中漏掉任何东西...?当页面加载时,我没有用户设置,即我没有正确的清单文件。页面加载->应用程序启动->获取用户设置->在这里我知道要加载哪个清单。 - poa
好的,很公平。这是我不确定的过程部分。如果您的设置意味着您无法使用服务器端语言(如PHP或Ruby)在页面加载之前检索用户设置,那么我认为您最好的选择是在文档的<head>中运行一个JavaScript,它既可以检索用户设置,又可以以编程方式将<link rel="manifest" />插入到<head>中。 - Rounin
@Rounin 我尝试了你的解决方案(当然使用了我自己的图标),但在Chrome控制台中出现了很多错误。是否还有其他步骤缺失,以便正确识别清单href中的数据? - Sofía
嗨,@Sofia。你能否发一个新问题,请解释一下你已经撰写的代码以及代码返回了哪些错误。谢谢。一旦你发布了新问题,你可以在这里的评论中添加链接。谢谢。 - Rounin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接