天人合一物我相融,站点升级渐进式Web应用PWA(Progressive Web Apps)实践

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: PWA(Progressive web apps,渐进式 Web 应用)使用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序,说白了,PWA可以让我们的站点以原生APP的形式运行,但相比于安装原生APP应用,访问PWA显然更加容易和迅速,还可以通过链接来分享PWA应用。

PWA(Progressive web apps,渐进式 Web 应用)使用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序,说白了,PWA可以让我们的站点以原生APP的形式运行,但相比于安装原生APP应用,访问PWA显然更加容易和迅速,还可以通过链接来分享PWA应用。

有许多知名的网络平台已经将 PWA 方案落地,比如Twitter。选择增强的网站体验而不是原生应用。事实上使用PWA也确实从中获得了显而易见的益处。https://www.pwastats.com 这个网站上分享了许多案例研究,PWA相比于传统应用有以下好处:

1、减少应用安装后的加载时间,通过 Service Workers 来进行缓存,以此来节省带宽和时间。

2、当应用有可用的更新时,可以只更新发生改变的那部分内容。相比之下,对于一个原生应用而言,即便是最微小的改动也需要强制用户去进行热更新或者再次下载整个应用。
3、外观和使用感受与原生平台更加融为一体——应用图标被放置在主屏幕上,应用可以全屏运行等。
凭借系统通知和推送消息与用户保持连接,对用户产生更多的吸引力,并且提高转换效率。

诚然,从零开始研发PWA应用会有一定的成本,但如果我们本身就拥有基于Web的站点,那么就可以通过增加对应的配置文件和服务进行升级操作,直接拥有PWA应用。

HTTPS服务

首先PWA要求站点的请求方式为HTTPS,如果是生产环境,可以通过为Nginx服务器配置SSL的方式进行适配,但是线下环境测试PWA时就有点费劲了,所以通过openssl工具为本地域名localhost做自签证书:

openssl req -x509 -out localhost.crt -keyout localhost.key \  
  -newkey rsa:2048 -nodes -sha256 \  
  -days 3650 \  
  -subj '/CN=localhost' -extensions EXT -config <( \  
   printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

产出:localhost.crt和localhost.key文件,key是私用密钥openssl格式,通常是rsa算法。csr是证书请求文件,用于申请证书,在制作csr文件的时,必须使用自己的私钥来签署申,还可以设定一个密钥。

将文件放到项目的根目录下,随后在构建项目服务的时候配置即可,以Tornado为例:

server = httpserver.HTTPServer(app,xheaders=True,ssl_options={  
        "certfile": "./localhost.crt",  
        "keyfile": "./localhost.key",  
    })  
  
# 指定端口  
server.listen(443)

这里通过设置ssl\_options参数来导入私钥和证书,同时将端口改为HTTPS默认端口号443。如此,在本地也可以对PWA进行测试了,当然了,如果不需要本地操作,也可以跳过这步。

manifest.json配置文件

为了实现 PWA 应用添加至桌面的功能,除了要求站点支持 HTTPS 之外,还需要准备 manifest.json 文件去配置应用的图标、名称等信息。

以本站为例,在站点根目录创建manifest.json文件:

{  
    "name": "刘悦的技术博客",  
    "short_name": "刘悦的技术博客",  
    "description": "刘悦的技术博客",  
    "icons": [  
        {  
            "src": "https://v3u.cn/v3u/Public/images/pwa192.png",  
            "sizes": "192x192",  
            "type": "image/png"  
        },  
        {  
            "src": "https://v3u.cn/v3u/Public/images/pwa512.png",  
            "sizes": "512x512",  
            "type": "image/png"  
        }  
    ],  
    "background_color": "#FFF",   
    "theme_color": "#FFF",   
    "display": "standalone",   
    "orientation": "portrait",  
    "start_url": "/",   
    "scope": "/"   
}

由上至下,依次是 PWA 应用的名称、描述、图标文件、banner颜色、显示方式、开始页面的链接和 PWA 的作用域。为此我们需要提供两张不同分辨率的站点图标文件:

ServiceWorker服务

Service Worker是一个注册在指定源和路径下的事件驱动型Web Worker。它充当了Web应用程序与浏览器之间的代理服务器,进行资源在文件级别下的缓存与操控,拦截页面请求,实现在不同的情况下对不同请求的响应策略。

Service Worker本质上就是一个Web Worker,因此它具有Web Worker的特点:无法操作DOM、脱离主线程、独立上下文。

Service Worker还具有这些特点:只能在Https下使用、运行在浏览器后台,不受页面刷新影响、更强大的离线缓存能力(使用Cache API)、请求拦截能力、完全异步,不能使用同步API、持续运行,第一次访问页面后,Service Worker就会安装激活并持续运行,直到手动销毁。

以本站为例,在站点根目录创建sw.js文件,注意Service Worker文件位置一定得在根目录,如果不在根目录也要通过重写或者url映射让其可以通过根目录路径进行访问,如:https://v3u.cn/sw.js,否则浏览器会检测不到Service Worker服务:

var CACHE_NAME = 'v3u-cache-v1';  
var urlsToCache = [  
    '/',  
    '/v3u/Public/css/tidy_min.css'  
];  
  
self.addEventListener('install', function (event) {  
    event.waitUntil(  
        caches.open(CACHE_NAME).then(function (cache) {  
            console.log('Open cache');  
            return cache.addAll(urlsToCache);  
        }).then(function () {  
            self.skipWaiting();  
        })  
    );  
}); 

当我们为页面注册Service Worker后,Service Worker开始进行安装,安装成功之后,会在worker中触发install事件;如果安装失败,则进入废弃状态。

如果Service Worker逻辑文件更新(相关资源文件变动或者内部逻辑更新等),Service Worker会重新安装,如果这个时候,页面依然存在激活状态下的worker(旧的Service Worker),那么新的worker会进入waiting状态进行等待,直到我们主动去操作worker强制其更新,或者等待用户关闭所有页面,这个时候新的worker才会进入到激活状态。

在install事件中,我们使用caches.open方法打开cache对象,并通过cache.addAll缓存所有我们列出的文件。如果Service Worker存在更新,我们使用skipWaiting跳过等待,直接强制新的worker进入激活状态。

随后,添加fetch事件:

self.addEventListener('fetch', function(event){  
        if(event.request.method !== 'GET') return;  
        event.respondWith(  
            caches.match(event.request).then(function(response){  
                if(response){  
                    console.log('return caches');  
                    return response;  
                }else{  
                    return fetch(event.request).catch(function(){  
                        if(/\.html$/.test(event.request.url))  
                            return caches.match('/html/neterror.html');  
                    });  
                }  
            })  
        )  
    });

这里只监听了全站的GET请求方式,即我们只希望控制资源请求。通过caches.match检查请求是否命中了缓存,如果命中,则直接返回缓存给用户,防止重复请求,节约资源。如果没有命中,则将使用fetch方法请求网络资源并返回给用户。当网络状态异常时(fetch().catch()),返回404页面的缓存给用户,告知用户当前处于无网络状态,不能访问相关页面。指定了一些页面和文件进行缓存,我们希望用户在无网络的情况下只能访问到我们指定缓存的页面。

当然,还有另外一种情况,我们指定了一些页面进行缓存(常用页面),当用户访问到一些不常用页面时,再对其进行缓存。这样,我们可以对资源配置进行优化,不过多的占用用户本地资源去缓存所有页面,因为PWA的缓冲本身是存储到客户端的,对于非所有用户的常用页面,按需缓存:

self.addEventListener('fetch', function(event){  
        if(event.request.method !== 'GET') return;  
        event.respondWith(  
            caches.match(event.request).then(function(response){  
                if(response){  
                    console.log('return caches');  
                    return response;  
                }else{  
                    return fetch(event.request).then(function(res){  
                        var responseToCache = res.clone();  
                        caches.open(CACHE_NAME).then(function(cache){  
                            catch.put(event.request, responseToCache);  
                        })  
                        return res;  
                    });  
  
                }  
            })  
        )  
    });

至此,ServiceWorker服务文件就撰写完成了。

生产环境上线配置:

分别将manifest.json和sw.js文件分别上传到生产环境之后,在页面的head标签中进行声明:

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

声明后,注意访问一下是否正确返回:https://v3u.cn/manifest.json

随后在页面中注册Service Worker服务:

<script>  
  if ('serviceWorker' in navigator) {  
    window.addEventListener('load', () =>  
        navigator.serviceWorker.register("/sw.js?v0")  
            .catch(() => {}) // ignore  
    );  
}  
</script>

这里首先判断当前浏览器的navigator是否支持serviceWorker,随后使用navigator.serviceWorker.register函数来注册Service Worker。其中,参数为要执行的worker逻辑文件路径,注意这个路径是基于origin的,而非当前文件。

接着键入组合键,打开chrome浏览器的开发者工具:

Mac系统上的“⌥+⌘+I”

Win系统上的“F12+Ctrl+Shift+I”

在Chrome 的应用标签下进行检查,看应用清单有没有读出你的 PWA 应用信息配置文件:

随后在serviceWorker标签下检查serviceWorker是否正确运行:

接着访问站点,在地址栏即可添加PWA应用:

访问效果:

结语

渐进式增强和响应式设计已经可以让我们构建对移动端非常友好的站点,而PWA则又在我们的身后轻轻地推了一把,黄河之水源可滥觞,星星之火正在燎原,一年以内,我们都将感到PWA的灼人温度。

相关文章
|
前端开发 算法 API
构建高性能图像处理Web应用:Next.js与TailwindCSS实践
本文分享了构建在线图像黑白转换工具的技术实践,涵盖技术栈选择、架构设计与性能优化。项目采用Next.js提供优秀的SSR性能和SEO支持,TailwindCSS加速UI开发,WebAssembly实现高性能图像处理算法。通过渐进式处理、WebWorker隔离及内存管理等策略,解决大图像处理性能瓶颈,并确保跨浏览器兼容性和移动设备优化。实际应用案例展示了其即时处理、高质量输出和客户端隐私保护等特点。未来计划引入WebGPU加速、AI增强等功能,进一步提升用户体验。此技术栈为Web图像处理应用提供了高效可行的解决方案。
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
IDE 开发工具 Python
魔搭notebook在web IDE下,使用jupyter notebook,python扩展包无法更新升级
魔搭notebook在web IDE下,使用jupyter notebook,python扩展包无法更新升级,不升级无法使用,安装python扩展包的时候一直停留在installing
353 4
|
开发框架 JSON 中间件
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。
|
缓存 前端开发 应用服务中间件
Web端实时通信技术SSE在携程机票业务中的实践应用
本文介绍了携程机票前端基于Server-Sent Events(SSE)实现服务端推送的企业级全链路通用技术解决方案。文章深入探讨了 SSE 技术在应用过程中包括方案对比、技术选型、链路层优化以及实际效果等多维度的技术细节,为类似使用场景提供普适性参考和借鉴。该方案设计目标是实现通用性,适用于各种网络架构和业务场景。
423 1
|
缓存 前端开发 应用服务中间件
Web端实时通信技术SSE在携程机票业务中的实践应用
本文介绍了携程机票前端基于Server-Sent Events(SSE)实现服务端推送的企业级全链路通用技术解决方案。文章深入探讨了 SSE 技术在应用过程中包括方案对比、技术选型、链路层优化以及实际效果等多维度的技术细节,为类似使用场景提供普适性参考和借鉴。
522 7
|
Web App开发 前端开发 JavaScript
鸿蒙5开发宝藏案例分享---Web适配一多开发实践
这是一份实用的鸿蒙Web多设备适配开发指南,针对开发者在不同屏幕尺寸下的布局难题提供了解决方案。文章通过三大法宝(相对单位、媒体查询和窗口监听)详细介绍如何实现智能适配,并提供了多个实战案例,如宫格布局、对话框变形和自适应轮播图等。此外,还分享了调试技巧及工具推荐,帮助开发者快速上手并优化性能。最后鼓励读者实践探索,并提示更多官方资源等待发现。
|
中间件 关系型数据库 数据库
docker快速部署OS web中间件 数据库 编程应用
通过Docker,可以轻松地部署操作系统、Web中间件、数据库和编程应用。本文详细介绍了使用Docker部署这些组件的基本步骤和命令,展示了如何通过Docker Compose编排多容器应用。希望本文能帮助开发者更高效地使用Docker进行应用部署和管理。
467 19
|
存储 消息中间件 缓存
支持百万人超大群聊的Web端IM架构设计与实践
本文将回顾实现一个支持百万人超大群聊的Web端IM架构时遇到的技术挑战和解决思路,内容包括:通信方案选型、消息存储、消息有序性、消息可靠性、未读数统计。希望能带给你启发。
775 0
支持百万人超大群聊的Web端IM架构设计与实践
|
9月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
637 4

热门文章

最新文章