Drupal开发者的渐进式网络应用程序指南

225 阅读14分钟

Digital creative of a browser on the internet

渐进式网络应用程序(PWA)得到了一些顶级科技公司的支持,包括谷歌和微软,他们的共同目标是"网络应用程序应该能够做任何iOS、Android或桌面应用程序能够做的事情。" PWA可以为处于各种不同阶段的企业增加价值。所有项目都有限制,无论是开发资源、时间表、预算还是技术债务。即使有 "无限的资源",从一个单一的代码库中开发一个应用程序,使用众所周知的网络技术,可以实现一个更无摩擦、更合理的发布周期。

免责声明:

  • PWA是不同技术的集合,在网络浏览器中结合起来,创造一种 "类似应用程序 "的体验。
  • 这些信息是从架构师的角度出发,选择和实施各种技术,共同构建一个产品。
  • 下面是在应用商店推出Drupal网站的一个高层次的端到端概要。每个部分都可以成为自己的深度博文。
  • 这些技术是针对Drupal编写的,但你可以将其中许多技术应用于所有的网络应用。

什么是PWA?

What is PWA

图片由:

(Alex Borsody, CC BY-SA 4.0)

实施PWA的好处:

  • 增加Lighthouse得分和SEO。
  • 单一代码库。
  • 无摩擦的测试。
  • 开发周期的即时反馈回路。
  • 使用现有的PaaS部署工作流程,包括Acquia, Pantheon, Platform.sh等。
  • 使用广泛的开发人员熟悉的技能的网络技术。
  • 提供唯一的跨平台开发解决方案,提供成熟的桌面体验。
  • 提供无限的选项来定制设计,而不依赖跨平台框架的有限的UI组件。

这篇文章涵盖了PWA部署的一些基本要点。在架构师和开发人员层面上,有许多细节需要考虑。以下是讨论的主题。

  • PWA的最低要求和Drupal PWA模块作为一个起点。
  • 在应用商店发布。
  • 你需要知道的关于让你的PWA感觉像应用程序的一切。

Drupal.org上的PWA模块

Drupal PWA模块是一个解决方案,它为缓存策略和离线能力生成一个服务工作者。它的次要功能也是生成一个manifest.json ,所以一旦安装,它将满足一个PWA开箱即用的基本要求

该模块的服务工作者有一些功能,为Drupal特有的行为提供了独特的解决方案,尽管你也可以将这些解决方案应用于Drupal以外的应用程序。

Drupal PWA module

图片由:

(Alex Borsody, CC BY-SA 4.0)

离线缓存

使用服务工作者的离线缓存是定义PWA的功能之一。

下面的图片总结了服务工作者如何作为一个代理(坐在客户端和互联网/网络服务器之间)来拦截来自浏览器的HTTP请求。

在对/about 页面的第一次请求中,浏览器到达网络,在从服务器返回200响应后,Javascript服务工作者调用cache.put(),将HTML和所有资产存储在Cache API中。

Offline caching example in service worker

图片由:

(Alex Borsody, CC BY-SA 4.0)

在第二次旅行中,服务工作者完全绕过网络,从用户的浏览器中的Cache API存储中提供页面,即时加载该页面。它也可以离线加载该页面。

Second visit to site

图片由:

(Alex Borsody, CC BY-SA 4.0)

浏览器可以预存页面,使其在用户访问前即时加载,甚至在访问前离线加载。然而,由于在Drupal中,CSS/JS文件名在压缩后会发生变化,因此该解决方案必须解决在通过服务工作者预存这些资产之前识别这些资产的问题。它通过内部请求管理面板中设置的URL并从DOM中提取资产来做到这一点。这允许服务工作者安装事件从这些文件中获取所有的CSS/JS和图片,以存储在Cache API中。然后,完整的页面将可以离线查看,并立即加载,即使用户从未首先访问过它们。

Service worker

(Alex Borsody, CC BY-SA 4.0)

Offline caching demo

(Alex Borsody, CC BY-SA 4.0)

下面,我从管理面板中设置的URL中获取所有的资产,以便以后注入到服务工作者的预缓存资产阵列中。在D8中,我把请求改为使用Drupal::httpClient(),它是D7中**drupal_http_request()**的更新版本,是PHP Guzzle库的一个封装器。

 foreach ($pages as $page) {
      try {
        // URL is validated as internal in ConfigurationForm.php.
        $url = Url::fromUserInput($page, ['absolute' => TRUE])->toString(TRUE);
        $url_string = $url->getGeneratedUrl();
        $response = \Drupal::httpClient()->get($url_string, array('headers' => array('Accept' => 'text/plain')));

这段代码匹配了所有需要的资产。

// Get all DOM data.
      $dom = new \DOMDocument();
      @$dom->loadHTML($data);

      $xpath = new \DOMXPath($dom);
      foreach ($xpath->query('//script[@src]') as $script) {
        $resources[] = $script->getAttribute('src');
      }
      foreach ($xpath->query('//link[@rel="stylesheet"][@href]') as $stylesheet) {
        $resources[] = $stylesheet->getAttribute('href');
      }
      foreach ($xpath->query('//style[@media="all" or @media="screen"]') as $stylesheets) {
        preg_match_all(
          "#(/(\S*?\.\S*?))(\s|\;|\)|\]|\[|\{|\}|,|\"|'|:|\<|$|\.\s)#ie",
          ' ' . $stylesheets->textContent,
          $matches
        );
        $resources = array_merge($resources, $matches[0]);
      }
      foreach ($xpath->query('//img[@src]') as $image) {
        $resources[] = $image->getAttribute('src');
      }
    }

下面,你可以看到在浏览器中输出的经过处理的serviceworker.js 文件的最终结果。服务工作者中的变量被替换为要缓存的资产的路径。

Final test of offline caching

(Alex Borsody, CC BY-SA 4.0)

手机之家卸载

该模块提供了另一个聪明的功能--卸载时负责任的清理。该模块发送一个请求回模块创建的URL。如果该URL不存在,就意味着该模块已经被卸载了。然后,服务工作者解除注册,并删除所有留在用户浏览器上的相关缓存。

// Fetch phone-home URL and process response.
  let phoneHomeUrl = fetch(PWA_PHONE_HOME_URL)
  .then(function (response) {
    // if no network, don't try to phone-home.
    if (!navigator.onLine) {
      console.debug('PWA: Phone-home - Network not detected.');
    }

    // if network + 200, do nothing
    if (response.status === 200) {
      console.debug('PWA: Phone-home - Network detected, module detected.');
    }


    // if network + 404, uninstall
    if (response.status === 404) {
      console.debug('PWA: Phone-home - Network detected, module NOT detected. UNINSTALLING.');
// Let SW attempt to unregister itself.
      Promise.resolve(pwaUninstallServiceWorker());
    }

    return Promise.resolve();
  })
  .catch(function(error) {
    console.error('PWA: Phone-home - ', error);
  });
};

测试注意事项

在开发中禁用该模块,因为它提供了一个额外的缓存层。对于CSS或其他具有缓存优先策略的资产,在推送到生产中的任何更改都应该增加服务工作者的版本以破坏缓存。

您可以在这个PWA模块文档页面上找到服务工作者的其他调试步骤。

在Android上使用Chrome控制台在移动设备上进行远程调试是可能的,而且可能会有帮助。

2.x版本

2.x和7.2x版本将服务工作者移植到Workbox,在那里你可以设置缓存策略。在这里,为不同的资产类型和路线设置缓存策略,从仅使用javascript Fetch API的约30行代码简化为约5行。有些人可能对库有抵触情绪,但这是谷歌对PWA的发展方向。

Workbox的缓存策略与Varnish等其他缓存层的策略类似。例如,默认情况下,图像资产和字体被设置为 "优先缓存",因此它们总是被即时提供。而HTML最好被设置为 "静态-同时验证"(stale-while-revalidate)。

Workbox and PWA module

形象代言人:

(Alex Borsody, CC BY-SA 4.0)

Workbox中也有一些功能,例如后台同步,即一个失败的帖子请求将在重新上线后重新尝试。

Offline cache

形象代言人:

(Alex Borsody, CC BY-SA 4.0)

关于服务工作者能做什么以及它可能有帮助的所有用例的更多信息,请查看GitHub上的W3服务工作者演示程序库。

编程和开发

红帽开发者博客

编程小抄

免费试用。红帽学习订阅

电子书。用Bash编程的介绍

Bash shell脚本小抄

电子书。现代化的企业Java

让你的网络应用进入应用商店

PWA builder是一个由微软提供的网络应用程序,你输入你的URL,它就会生成你需要提交给应用商店的一切。

对于Android,它使用TWA,对于iOS,它使用WebKit的WKWebView在本地SWIFT代码中包装你的Web应用。这些都是我从2013年开始使用的技术,当时Drupal还是一项热门技术,并被初创企业所使用。那些拥有移动优化的Drupal网站的企业希望它们能在应用商店中出现。在Android TWA之前,开发者使用Webview,而在WKWebView之前,有UIWebView。

最近PWA builder增加了一个使用WKWebView的iOS解决方案,这证实了我的信念,即这是让你的PWA进入App Store的最佳选择。Maximilian Firtman在他的课程 "Creating Progressive Web Apps with Vue "中也揭示了这是一个解决方案,我购买了这门课程以看到他对这个问题的答案。

PWA模块提供了你通过PWA Builder运行所需的一切。

  • 对于安卓,它使用TWA创建一个轻量级的.apk/.aap,以提交给Play Store 800kb。
  • 对于iOS,它将你的网站包裹在WKWebView中,并提交给App Store。

我把PWA builder放在一起的实时演示在这里。[[编辑 - 缺少链接]]

安卓和TWA

谷歌和Chromium团队是目前PWA背后最强大的驱动力。因此,TWA是专门为让你的PWA进入Play商店而设计的。相反,WKWebView本质上是一种不被苹果明确支持的变通方法。然而,WKWebView是非常强大的,尽管苹果没有宣传这一点,也没有很多关于其功能的文档。

受信任的网络活动本质上是一个全屏运行的Chrome进程,有状态栏和加载屏幕。该线程与你手机上的Chrome应用在同一进程中运行。例如,如果你在Chrome浏览器上登录,你就会在TWA应用上登录。为了澄清由此可能产生的任何混淆,TWA团队增加了一个 "祝酒词",即用户第一次打开应用时,通知显示 "在Chrome中运行"。这只发生在第一次安装该应用时。这种烦恼足以让一些团队放弃TWA,而使用WebView类;然而,谷歌不鼓励这样做,因为你失去了Chrome网络浏览器中的一切。

谷歌关于使用TWA的主要观点是。

  • Chrome浏览器功能完整。
  • 比Webview更快。
  • 常青(总是最新版本的Chrome)。

额外的有用功能。

  • Chrome处理无摩擦的OAuth请求。
  • 与首选浏览器共享cookies、本地存储和保存的设置。

下面是使用TWA而不是Webview包装器时得到的所有东西的对比图。

Google TWA

形象代言人:

(Alex Borsody, CC BY-SA 4.0)

Webkit。WKWebView

在App Store上发布有几个注意事项。WKWebView本质上是一种变通方法,而不是苹果隐含认可的启动本地应用的方法。这方面有一些注意事项。最重要的是要注意苹果的最低功能准则

根据我的经验,如果你尽一切可能使你的网络应用程序具有有用的功能,你就会得到批准。使用Webkit API来增强你的网络应用程序是在你的网站之外提供额外功能的另一种方式。

一种技术是根据start_url来设置一个cookie。例如,添加一个参数,如myapp.com?ios_app,并设置一个cookie,以确定单独的样式表或自定义逻辑。

考虑一下下面的示例实现。

注意:这种技术不应该与苹果有限的添加到主屏幕的支持相混淆,你通常听到的是苹果+PWA的情况。我不会介绍这个,因为这不是用户期望的体验。

PWA生成器提供了用WKWebView包装网站以提交应用商店所需的最低功能。对于生物识别或推送通知等功能,你需要一个WKWebView的自定义实现。

在下面的图形中,您可以看到提供的源文件。然后你就可以轻松地在XCode中编译你的应用程序,并将其提交给应用程序商店。

Source code

图片由:

(Alex Borsody, CC BY-SA 4.0)

PWA Builder提供

  • wKWebView.scrollView.bounces = false滚动出视图时不会弹出
  • 服务工作者支持
  • 捷径URL捕获
  • 允许的导航范围
  • 状态栏定制
  • 来自清单道具的闪屏
  • 从JS代码中了解iOS应用
  • 支持Mac商店

WKWebView的自定义实现可以提供。

  • 推送通知。推送通知可以通过发布与Drupal UID相匹配的设备ID来实现,例如,可以从URL**/user/{uid}/edit**中提取。
  • 生物识别:除了user/login和user/register之外,生物识别在所有的页面上都得到了实现,而且cookie的最大过期时间也被延长。每次关闭和重新打开应用程序时都会显示生物识别。
  • WKUIDelegate。呈现本地UI元素,如警报、输入或上下文菜单。
  • evaluateJavaScript()。执行任何Javascript。这里的可能性是无穷的。
  • 使用关联域的密码管理。在你的/.well-known 目录中放置一个公钥对,将允许你的本地应用程序信任你的网站并自动填充密码。

查看WKWebView+的README.md,这是我正在做的一个项目,可以很容易地将这种增强的功能集成到任何iOS PWA中。

WKWebView的缺点

在实施WKWebView之前,请注意以下几点。

  • 前端开发人员需要转变思维模式,以正确调试PWA。虽然它依赖于网络技术,但也有一个学习曲线。
  • 如果没有一个原生的iOS开发者,某些功能是不可能实现的。然而,WKWebView+就是为了解决这个问题而设计的。
  • 虽然苹果和PWA的前景看起来很好,但像往常一样,你要听从下一个Safari版本的摆布。

继续前进

TWA的许多功能只适用于基于Chromium的浏览器。Webkit移动/WKWebView滞后。这种滞后包括推送通知、"添加到主屏幕 "和整体网络浏览器标准。Maximilian Firtman的博客是目前对最新的Safari中的更新进行总结的最佳资源之一,即使这些更新没有在发布说明中公布

乐观的前景是,WKWebView是基于开源项目Webkit的,而且从事Chromium和WebKit的开发者之间也有合作。任何人都可以创建一个问题和拉动请求。通常情况下,Chrome中已经实现的功能会向Webkit提交同样的补丁。

让它像应用程序一样

服用了所有正确维生素的网站 PWA本质上是一个网络技术的集合,结合起来使你的网络体验像应用程序一样,就像网站 "服用了所有正确的维生素"。下面我确定了构成一个好的PWA的要点。

  • 用户体验/用户界面。视觉问题的解决是使你的网站感觉像一个应用程序的核心所在。一个对设计和细节(如动画、输入/字体大小和滚动问题)有独到见解的优秀CSS开发者是必不可少的。
  • 保持与应用程序一样的增强功能。保持前端代码的更新和跨WebKit/Chrome的兼容需要研究和定期更新,特别是当新版本的iPhone发布时。
  • 实施扩展的网络功能。Chromium团队不断改进浏览器的体验。这可以在Project Fugu项目中得到追踪,这是一个总体的网络能力项目。最接近于全面的PWA文档是在webdev上。
  • 页面速度:我谈到了用服务工作者进行缓存,但还有无数其他技术和技巧。

一些类似于应用程序的增强功能的例子包括使用网络开发人员常用的HTML/CSS/JS技术,然后使它们在实施、测试和部署时不产生摩擦。你可以在这里找到一个使用许多这些建议的网络应用的好例子。

建议包括。

  • Javascript触摸事件。禁用捏合变焦,增加滑动/多点触摸手势。
  • CSS。
    • 最小化/优化CSS并应用Lighthouse建议。
    • "类似应用程序的输入/字体大小,确保所有东西都适合在视口中使用;使其在视觉上看起来像一个应用程序。
    • 巧妙地使用预加载器。
  • 利用cookie。根据应用程序的启动URL来设置cookie。
  • HTML属性。
  • Ajax API(Drupal专用),Websockets,或SPA框架。
  • iPhone的具体建议。

iPhone X status bar

Image by:

(Alex Borsody, CC BY-SA 4.0)

总结

PWA汇集了不同的技术,在网络浏览器中创造类似于应用程序的体验。我概述了一个Drupal网站的PWA实现方法,但其他选择肯定也有类似的设计。PWA的哪些实现方式可能有助于你的组织的用户体验?

查看WKWebView+的README.md,这是我正在做的一个项目,可以很容易地将这种增强的功能整合到任何iOS PWA中。

Ionic是Cordova的精神继承者,是一个流行的框架,它也利用WKWebView来构建原生iOS。