Ahm*_*rib 13 javascript manifest reactjs progressive-web-apps manifest.json
我有一个具有安全连接 (https) 的已部署应用程序。
我设法使用 Google Chrome 中的此功能将其添加到我的 Android 主屏幕:

问题是,如果我不在应用程序中添加执行此操作的按钮,用户不太可能执行此操作。
经过一番研究后,我尝试将此处的代码改编为我的 React 应用程序。
所以我改变了这个:
let deferredPrompt;
const addBtn = document.querySelector(".add-button");
addBtn.style.display = "none";
window.addEventListener("beforeinstallprompt", (e) => {
// Prevent Chrome 67 and earlier from automatically showing the prompt
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
// Update UI to notify the user they can add to home screen
addBtn.style.display = "block";
addBtn.addEventListener("click", (e) => {
// hide our user interface that shows our A2HS button
addBtn.style.display = "none";
// Show the prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
deferredPrompt.userChoice.then((choiceResult) => {
if (choiceResult.outcome === "accepted") {
console.log("User accepted the A2HS prompt");
} else {
console.log("User dismissed the A2HS prompt");
}
deferredPrompt = null;
});
});
});
Run Code Online (Sandbox Code Playgroud)
对此:
export class AddToHomeScreenButton extends Component {
constructor() {
super();
this.state = {
deferredPrompt: null,
};
this.onClick = this.onClick.bind(this);
}
componentDidMount() {
let deferredPrompt;
window.addEventListener("beforeinstallprompt", (e) => {
console.log(
" ~ file: AddToHomeScreenButton.js:46 ~ AddToHomeScreenButton ~ window.addEventListener ~ beforeinstallprompt"
);
// Prevent Chrome 67 and earlier from automatically showing the prompt
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
console.log(
" ~ file: AddToHomeScreenButton.js:22 ~ AddToHomeScreenButton ~ window.addEventListener ~ deferredPrompt",
deferredPrompt
);
this.setState({ deferredPrompt });
});
}
onClick(e) {
// hide our user interface that shows our A2HS button
// addBtn.style.display = "none";
// Show the prompt
const { deferredPrompt } = this.state;
console.log(
" ~ file: AddToHomeScreenButton.js:49 ~ AddToHomeScreenButton ~ onClick ~ deferredPrompt",
deferredPrompt
);
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
deferredPrompt.userChoice.then((choiceResult) => {
console.log(
" ~ file: AddToHomeScreenButton.js:53 ~ AddToHomeScreenButton ~ deferredPrompt.userChoice.then ~ choiceResult",
choiceResult
);
console.log(
" ~ file: AddToHomeScreenButton.js:55 ~ AddToHomeScreenButton ~ deferredPrompt.userChoice.then ~ choiceResult.outcome",
choiceResult.outcome
);
if (choiceResult.outcome === "accepted") {
console.log("User accepted the A2HS prompt");
} else {
console.log("User dismissed the A2HS prompt");
}
this.setState({ deferredPrompt: null });
});
}
render() {
const { deferredPrompt } = this.state;
return (
<span>
{!!deferredPrompt && (
<Button
className=".add-button"
color="danger"
type="button"
onClick={this.onClick}
>
Add to home screen
</Button>
)}
</span>
);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,什么也没发生,我也不知道为什么。我检查桌面中的控制台以及其中的代码:
window.addEventListener("beforeinstallprompt", (e) => {
Run Code Online (Sandbox Code Playgroud)
不会被执行。
我认为这是有道理的,因为我相信这个功能不应该在桌面上工作。但是,它也不适用于已部署的应用程序中的移动设备。
但是,正如我所说,我设法使用 chrome“添加到主屏幕”按钮将该应用程序添加到我的 Android 主屏幕。它的工作原理就像一个本机应用程序。
我在这里发现可能有多种原因导致beforeinstallprompt没有被触发
beforeinstallprompt 仅在某些条件成立时才会被触发:
- 不得已安装 PWA 满足用户参与度
- 启发式(以前,用户必须与域交互至少 30 秒,这不再是要求)。
- 您的 Web 应用程序必须包含 Web 应用程序清单。
- 您的 Web 应用程序必须通过安全的 HTTPS 连接提供服务。
- 已向 fetch 事件处理程序注册了一个 Service Worker。
所有这些条件都满足。
这是网络应用程序清单:
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
Run Code Online (Sandbox Code Playgroud)
还有一个 Service Worker 文件:
// This optional code is used to register a service worker.
// register() is not called by default.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
} else {
// Is not localhost. Just register service worker
registerValidSW(swUrl, config);
}
});
}
}
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (!installingWorker) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl, {
headers: { 'Service-Worker': 'script' }
})
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (
response.status === 404 ||
(!!contentType && contentType.indexOf('javascript') === -1)
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
}
})
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}
Run Code Online (Sandbox Code Playgroud)
当我在桌面浏览器上打开应用程序时,我在“应用程序”>“清单”中看到以下内容:
但是,我想这些与手机浏览器无关。另外,该应用程序确实是使用 chrome“添加到主屏幕”按钮安装的。所以是可以安装的。
知道如何调试为什么我添加的按钮不起作用以及如何修复它吗?
小智 9
我第一次尝试参考其他来源创建 PWA。希望对您有帮助。
以下是我为获得预期输出而遵循的步骤。
create-react-app首先,使用with创建一个 React 应用程序
npx create-react-app pwa-app --template cra-template-pwa
Run Code Online (Sandbox Code Playgroud)
这将为我们的 PWA 创建一些必需的文件/更改,例如,
通过在 src/index.js 中添加此行来注册 serviceWorker
serviceWorkerRegistration.register(); // by default it will be serviceWorkerRegistration.unregister();
Run Code Online (Sandbox Code Playgroud)
打开 public/manifest.json 以根据需要编辑应用程序名称和图标。
现在,让我们添加一个钩子来创建和调用安装提示符,
src/AddToHomeScreen.jsx
import * as React from "react";
// Taken from: https://gist.github.com/rikukissa/cb291a4a82caa670d2e0547c520eae53
export function useAddToHomescreenPrompt() {
const [prompt, setState] = React.useState(null);
const promptToInstall = () => {
if (prompt) {
return prompt.prompt();
}
return Promise.reject(
new Error(
'Tried installing before browser sent "beforeinstallprompt" event'
)
);
};
React.useEffect(() => {
const ready = (e) => {
e.preventDefault();
setState(e);
};
window.addEventListener("beforeinstallprompt", ready);
return () => {
window.removeEventListener("beforeinstallprompt", ready);
};
}, []);
return [prompt, promptToInstall];
}
Run Code Online (Sandbox Code Playgroud)
在 src/App.js (或任何组件)中,
import { useAddToHomescreenPrompt } from "./AddToHomeScreen";
Run Code Online (Sandbox Code Playgroud)
调用钩子,
const [prompt, promptToInstall] = useAddToHomescreenPrompt();
Run Code Online (Sandbox Code Playgroud)
添加 onClick 到按钮,
<button onClick={promptToInstall}>Add to Home Screen</button>
Run Code Online (Sandbox Code Playgroud)
现在,在部署站点后,应该安装应用程序。
要检查应用程序是否已安装,请将其添加到 public/manifest.json
"related_applications": [
{
"platform": "webapp",
"url": "https://yourwebsite.com/manifest.json"
}
],
Run Code Online (Sandbox Code Playgroud)
并使用此功能查找已安装的应用程序,
src/App.js
const [isAppInstalled, setIsAppInstalled] = useState(false);
React.useEffect(() => {
isPWAInstalled();
}, []);
const isPWAInstalled = async () => {
if ("getInstalledRelatedApps" in window.navigator) {
const relatedApps = await navigator.getInstalledRelatedApps();
let installed = false;
relatedApps.forEach((app) => {
//if your PWA exists in the array it is installed
console.log(app.platform, app.url);
if (
app.url ===
"https://yourwebsite.com/manifest.json"
) {
installed = true;
}
});
setIsAppInstalled(installed);
}
};
Run Code Online (Sandbox Code Playgroud)
在渲染中,
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
{!isAppInstalled ? (
<button onClick={promptToInstall}>Add to Home Screen</button>
) : (
<div>Thanks for installing our app</div>
)}
{status.map((text) => (
<div style={{ fontSize: "14px", marginTop: "5px" }}>{text}</div>
))}
</header>
</div>
);
Run Code Online (Sandbox Code Playgroud)
此外,我们可以在 public/manifest.json 文件中添加快捷方式、屏幕截图。
我希望我没有错过任何事情。
我的参考资料:
https://create-react-app.dev/docs/making-a-progressive-web-app/
https://gist.github.com/rikukissa/cb291a4a82caa670d2e0547c520eae53
https://web.dev/install-criteria/
| 归档时间: |
|
| 查看次数: |
5697 次 |
| 最近记录: |