MeteorCat / PWA应用|轻应用

Created Mon, 14 Oct 2024 14:56:59 +0800 Modified Wed, 29 Oct 2025 23:24:53 +0800
1961 Words

PWA应用

如果 Chrome 浏览器版本比较新就可以直接让其安装到桌面上作为应用来处理:

image

无论手机还是桌面浏览器都能将网页安装到桌面从而变成 APP 来使用.

这里实现的方法其实十分简单, 只需要在 html 页面上追加 manifest 声明网页元数据:

<head>
    <link rel="manifest" href="manifest.json">
</head>

这里的 manifest.json 就是声明 PWAJSON 格式配置文件, 实际上就是相当于调用本地浏览器的 Web 应用入口, 也就是 轻应用 的概念的由来, 无须复杂的桌面|移动端开发来构建的应用.

manifest.json 配置是所有浏览器通用的, 这里提供 Mozilla 的官方说明: Mozilla Manifest

配置的样例如下:

{
  "name": "HackerWeb",
  "short_name": "HackerWeb",
  "start_url": ".",
  "display": "standalone",
  "background_color": "#fff",
  "description": "A simply readable Hacker News app.",
  "icons": [
    {
      "src": "images/touch/homescreen48.png",
      "sizes": "48x48",
      "type": "image/png"
    },
    {
      "src": "images/touch/homescreen72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "images/touch/homescreen96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "images/touch/homescreen144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "images/touch/homescreen168.png",
      "sizes": "168x168",
      "type": "image/png"
    },
    {
      "src": "images/touch/homescreen192.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "related_applications": [
    {
      "platform": "web"
    },
    {
      "platform": "play",
      "url": "https://play.google.com/store/apps/details?id=cheeaun.hackerweb"
    },
    {
      "platform": "windows",
      "id": "example.app1"
    },
    {
      "platform": "amazon",
      "url": "https://www.amazon.com/product/dp/B000XA1000"
    }
  ]
}

这里挑选需要说明的配置讲解:

  • name: 应用名称, 安装之后显示的应用名称
  • short_name: 短名, 在名称过长的时候展示的缩略名称
  • start_url: 启动的应用路径, 支持网页路径和本地相对路径, 这里地址可以追加 ?utm_source=pwa 识别启动的地址
  • description: 应用详情信息, 可以显示应用具体描述信息, 可有可无的添加项
  • theme_color: 启动时的边框和页面主题色, 用于让应用颜色让更加贴合应用内部, 可有可无的添加项
  • display: 启动时候的显示方式, 常规采用 standalone 处理, 具体显示模式:
    • fullscreen: 启动时候应用采用全屏覆盖屏幕, 注意他会尽可能隐藏浏览器UI并让内容填充屏幕
    • standalone: 启动时候象独立应用一样屏蔽隐藏掉本来浏览器的界面(导航栏、工具栏等), 让其更类似独立应用
    • minimal-ui: 和 standalone 类似, 但是不同的是他会尽可能UI缩小成按钮, 不同浏览器会呈现不同显示效果
    • browser: 浏览器默认配置, 启动时候和打开浏览器一致
  • orientation: 应用的显示方向, 桌面应用感知不到, 但是移动端有竖屏和横屏应用来处理(还有平板电脑之类), 具体显示方向:
    • landscape-primary|landscape-secondary: 横屏状态, 对应是 +-90° 的横屏差别(也就是左|右偏移的方向)
    • portrait-primary|portrait-secondary: 竖屏状态, 也是对应 +-90° 的竖屏差别
    • landscape: 会按照不同设备平台自由切换 landscape-primary|landscape-secondary, 也就是横屏处理
    • portrait: 同上, 都是按照设备平台来处理切换 portrait-primary|portrait-secondary, 也就是竖屏处理
    • natural: 同上, 按照设备自由切换成 portrait-primary(竖屏)|landscape-primary(横屏), 不同 any 自由旋转角度的强制方向
    • any: 根据屏幕旋转角自由切换 landscape-primary|landscape-secondary|portrait-primary|portrait-secondary 配置
  • icons: 设备显示图标的列表, 用于指定轻应用的图标尺寸等信息, 也是比较关键配置项
    • src: 图标URL地址, 支持 URL 和本地相对图标
    • type: 图标的 MIME 类型, 不填写浏览器也会采用默认图片处理去匹配检索对应类型, 建议最好 image/png 并直接声明
    • sizes: 图标宽高, 注意如果单个图片支持多种尺寸可以通过空格声明, 如 48x48 96x96 128x128 这样声明支持多尺寸图标
  • prefer_related_applications: 用于是否弹出安装原生本地 app 应用的提示, 默认为 false, 详情见下.
  • related_applications: 只有在 prefer_related_applications:true 情况下才会生效用于转原生应用下载平台地址.
    • platform: 必须填写的下载平台, 比较常见的 play(Google商店)|itunes(苹果商城)|windows(Win桌面), 具体可见 平台声明
    • url: 下载的平台跳转的 URL 地址
    • id: 应用下载平台上表示应用程序的标识 ID

以上就是比较常用到的 PWA 配置项目, 具体可以按照自身所需的情况处理从而开发泛用的轻度应用.

关于 display 配置, 可以通过 display-mode 这个查询条件去指定在不同的显示类型下不同的显示样式, 如:

/* display:fullscreen 适用的 CSS 样式 */
@media all and (display-mode: fullscreen) {
    body {
        margin: 0;
    }
}

/* display:standalone 适用的 CSS 样式 */
@media all and (display-mode: standalone) {
    body {
        margin: 1px;
    }
}

/* display:minimal-ui 适用的 CSS 样式 */
@media all and (display-mode: minimal-ui) {
    body {
        margin: 2px;
    }
}

/* display:browser 适用的 CSS 样式 */
@media all and (display-mode: browser) {
    body {
        margin: 3px;
    }
}

站点在同一浏览器中被访问至少两次的时候, 默认会调用浏览器的安装提示引导应用去将 PWA 应用安装到本地, 这里提供 JS 事件来用于监听处理:

// 判断用户是否安装此应用
// beforeinstallprompt 事件返回一个名为 userChoice 的 Promise 对象, 并在当用户对横幅进行操作时进行解析
// promise 会返回属性 outcome, 该属性的值为 dismissed 或 accepted, 如果用户将网页添加到主屏幕, 则返回 accepted
window.addEventListener('beforeinstallprompt', function (e) {
    // beforeinstallprompt event fired
    e.userChoice.then(function (choiceResult) {
        if (choiceResult.outcome === 'dismissed') {
            console.log('用户取消安装应用');
        } else {
            console.log('用户安装了应用');
        }
    });
});

// 取消或延迟安装横幅的触发事件
// 网站虽然不能主动触发安装横幅的显示事件, 但是当该事件被浏览器触发之后, 可以对其进行取消或者延迟
// 通过阻止 beforeinstallprompt 事件的默认行为, 即可取消横幅弹出
window.addEventListener('beforeinstallprompt', function (e) {
    e.preventDefault();
    return false;
});


// 通过按钮点击事件触发横幅显示
// 阻止系统默认的安装弹出, 让网页按钮接管安装弹出从而安装到本地
var dfdPrompt = null;
var button = document.getElementById('btn');// 自定义点击按钮

// 禁用系统默认弹出
window.addEventListener('beforeinstallprompt', function (e) {
    dfdPrompt = e; // 存储事件
    button.style.display = 'block'; // 显示按钮
    e.preventDefault(); // 阻止默认事件
    return false;
});

// 按钮触发弹出安装下载
button.addEventListener('click', function (e) {
    if (dfdPrompt == null) {
        return;
    }
    dfdPrompt.prompt(); // 通过按钮点击事件触发横幅显示

    // 监控用户的安装行为
    dfdPrompt.userChoice.then(function (choiceResult) {
        alert(choiceResult.outcome);
    });
    button.style.display = 'none'; // 隐藏按钮
    dfdPrompt = null;
});

PWA 应用可以依托浏览器技术开发出更加编写的轻度应用, 不需要复杂安卓|iOS打包技术从而降低开发难度; 但很多原生系统功能只能看浏览器的规范支持, 同时对于网络依赖也更深(网络中断连本地资源都无法加载).

不过回过头来说很多应用功能大部分比较简单, 如果后面扩展起来最多 prefer_related_applications 设为 true 引流转原生应用也可以.