【问题标题】:How to create dynamic manifest.json file in PWA and ReactJS?如何在 PWA 和 ReactJS 中创建动态 manifest.json 文件?
【发布时间】:2018-10-25 20:09:09
【问题描述】:

我有一个项目需要为我的 PWA (ReactJS) 创建一个动态 manifest.json 文件。

请看下面我的代码:

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 (
                ................
            );
        }
}

我对这种事情不熟悉。我该如何开始?

【问题讨论】:

  • 这里的人们可能很难提供帮助,因为他们可能不确定您在哪里卡住了。您是否尝试过您描述的任务,并且遇到了某种困难?如果您可以缩小问题范围,这可能会帮助人们帮助您。

标签: javascript reactjs react-redux


【解决方案1】:

如果您想创建动态 manifest.json,您希望在 HTML 中有一个带有 rel="manifest" 但没有 href 属性的链接标签。稍后使用此标签填充您的清单。如

<!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>title</title>
        <link rel="manifest" id="my-manifest-placeholder">
      </head>
      <body>
        <!-- page content -->
      </body>
    </html>

使用 JSON 对象设置清单

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);

【讨论】:

  • 很遗憾,此解决方案在某些情况下无法正常工作 - here 解释了原因。
【解决方案2】:

灵感来自 @Sanjeet kumar 为我的 NextJs 应用程序提供的解决方案:

// _document.tsx
<link href="/manifest.json" rel="manifest" id="manifest" />


// _app.tsx
import manifest from "../../public/manifest.json";

const manifestElement = document.getElementById("manifest");
const manifestString = JSON.stringify({
  ...manifest,
  start_url: `${homePagePath}${storeCode}`,
});
manifestElement?.setAttribute(
  "href",
  "data:application/json;charset=utf-8," + encodeURIComponent(manifestString)
);

【讨论】:

  • 使用这种方法给了我Manifest: property 'start_url' ignored, URL is invalid.
  • @SushiWaUmai 这可能是由于您对start_url 的定义方式 - 它应该按照here 的说明进行设置 - 例如,/.https://example.org/path。您可以使用Lighthouse PWA analysis tool 来验证它的设置是否正确。
【解决方案3】:

我在使用 Blob 时遇到了一些问题,它没有按预期在 android 中工作。下面的答案工作正常。

 var myDynamicManifest = {
  "name": "Your Great Site",
  "short_name": "Site",
  "description": "Something dynamic",
  "start_url": "<your-url>",
  "background_color": "#000000",
  "theme_color": "#0f4a73",
  "icons": [
      {
        src: "icon_size_36.png",
        sizes: "36x36",
        type: "image/png",
      },
      {
        src: "icon_size_48.png",
        sizes: "48x48",
        type: "image/png",
      },
      {
        src: "icon_size_72.png",
        sizes: "72x72",
        type: "image/png",
      },
      {
        src: "icon_size_96.png",
        sizes: "96x96",
        type: "image/png",
      },
      {
        src: "icon_size_144.png",
        sizes: "144x144",
        type: "image/png",
      },
      {
        src: "icon_size_192.png",
        sizes: "192x192",
        type: "image/png",
      },
      {
        src: "icon_size_512.png",
        sizes: "512x512",
        type: "image/png",
      },
    ]
  }
  const link = document.createElement("link");
  link.rel = "manifest";    
  const stringManifest = JSON.stringify(myDynamicManifest);
  link.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(stringManifest))
  document.head.appendChild(link);

【讨论】:

  • 我相信即使在 Android 上使用这种方法仍然存在问题 - 如果您更新 manifest.json,它可能无法应用更新。请看我对它的评论here
【解决方案4】:

不幸的是,使用blob:data: URL 的建议在某些情况下无法正常工作,因为manifest.json URL 应该是static

不要更改您的网络应用清单文件的名称或位置,这样做可能会阻止浏览器更新您的 PWA。

正如那篇文章所解释的,manifest.json 有一种特殊的更新机制(由非常具体的条件触发)——它不应该通过 URL 名称进行更新。

此外,Android 可能不再将应用识别为完整的(WebAPK 可安装)PWA,即使应用通过了 Lighthouse 检查。在这种情况下,它仍然作为常规 PWA “安装”,在应用启动图标的角落有一个丑陋的 Chrome 图标。我花了很多时间试图理解原因,最后偶然发现了那篇带有解释的文章。

所以请

  1. 从完全静态的 URL 提供动态 manifest.json,或
  2. 根据在应用程序的生命周期内不会改变的某些属性(例如主机名)确定 href(以便可以为不同的客户端提供不同的清单变体,但每个客户端的版本都有一个静态 URL) .

【讨论】:

  • 什么意思?您上面链接的解决方案实际上是用不同的data: 有效负载更改href 属性...
  • 感谢您的注意,我的意思更多是从动态从 URL 获取清单的角度来看。我已经更新了答案以使其更加清晰。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
  • 2020-09-02
  • 2019-11-11
  • 2019-01-08
相关资源
最近更新 更多