如何轻松地将您的网站转变为渐进式 Web 应用程序 (PWA) 简介

2025-05-24

如何轻松地将您的网站转变为渐进式 Web 应用程序 (PWA)

简介

渐进式 Web 应用 (PWA) 是一种新兴的流行方式,旨在将原生应用的体验带入普通或传统的 Web 应用。PWA 已被 Twitter、福布斯、阿里巴巴、Instagram、Flipkart 等一些大型公司广泛采用,并已逐渐普及。

因此,在本教程中,我们将把现有的网站转变为渐进式 Web 应用。现在就开始吧 :)

简介

我确信您现在一定已经听说过或读过有关渐进式 Web 应用程序的内容,如果您还没有听说过,那么这里就有。

渐进式 Web 应用程序 (PWA) 是一种通过 Web 交付的应用软件,使用 HTML、CSS 和 JavaScript 等常见 Web 技术构建而成。它旨在适用于任何使用符合标准浏览器的平台。其功能包括离线工作、推送通知和设备硬件访问,从而能够在桌面和移动设备上打造与原生应用程序类似的用户体验。

渐进式 Web 应用主要具有以下特点:

  • 可靠——它们可以立即加载,并且永远不会显示“无互联网连接”页面,即使在服务工作者缓存的帮助下,在不确定的网络条件下也是如此。

  • 快速——它们通过流畅的动画快速响应用户交互。

  • 引人入胜——它们感觉就像设备上的自然应用程序,具有身临其境的用户体验。

本教程的要求

  1. 基本网页设计技能(HTML、CSS 和 JS)

  2. 您需要在 HTTPS 上运行

  3. 您希望转换为 PWA 的正常运行的网站。

就像我说的,如果你理解整个概念以及它的实际工作原理,那么构建渐进式 Web 应用程序就非常简单和容易。

PWA 的构成要素

  1. Web 清单
  2. 服务工作者
  3. 您的静态网站
让我们开始吧

为了完成本教程,我们将把一个简单的随机报价 Web 应用转换为 PWA。所有文件都托管在Github上,演示代码可在此处获取。

因此,为了确保一切顺利,我们将使用 HTML、CSS 和 JavaScript 重建简单的随机报价网络应用程序。

最终项目
最终的项目将会是这个样子的。

那么让我们构建 UI。

创建新目录并创建这些文件

  • index.html

  • css/style.css

  • js/app.js

让我们构建标记

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>The Igala Facts you never knew</title>
    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
    <link href='https://fonts.googleapis.com/css?family=Roboto+Slab:400,700' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.2.3/animate.min.css">
</head>
<body>
    <div class="container">
        <div class="row">
          <div class="col-sm-6">
            <h1><span class="main-color">Random Igala</span><br />Facts</h1>
            <p>The best facts about Igala in one place. You can easily see the best facts and  share the ones you love on twitter with one click.</p>
          </div>
          <div class="col-sm-6">
            <div class="row">
              <div class="col-xs-6">
                <a id="next-quote" class="btn btn-lg btn-default btn-block" href="#"><i class="fa fa-refresh"></i> Next Fact</a>
              </div>
              <div class="col-xs-6">
                <a id="share" class="btn btn-lg btn-default btn-block" href="#" target="_top"><i class="fa fa-twitter"></i> Share</a>
              </div>
            </div>

            <div id="quote-box">
              <i id="quote-left" class="fa fa-quote-left"></i>
              <p id="quote"></p>
              <span id="author" class="main-color"></span>
              <i id="quote-right" class="fa fa-quote-right"></i>
            </div>

            <div class="row">       
              <div class="col-xs-12">
                <ul>
                  <li>Follow Us</li>
                  <li><a class="main-color" href="https://facebook.com/theigaladigital" target="_blank">@theigaladigital</a></li>
                    </ul>
                  </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div id="hidden"></div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
      <script src="js/app.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

就像我之前说的,本教程主要教你如何将现有的网站转换为渐进式 Web 应用程序,所以我不会详细介绍 HTML 或其他内容。

— 添加此内容css/app.css

body {
    background-color: rgb(0, 0, 0);
    color: white;
    padding-top: 50px;
    font-size: 18px;
    font-family: 'Roboto Slab', serif;
  }

  h1 {
    font-size: 4em;
    line-height: 70px;
    margin-bottom: 40px;
    font-weight: bold;
  }

  a:hover, a:focus, a:active {
    text-decoration: none;
    color: white;
    transition: color 0.8s;
  }

  .main-color {
    color: yellow;
    text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.2);
    font-weight: bold;
  }

  #quote-box {
    background-color: rgba(255, 255, 255, 0.3);
    border-radius: 10px;
    padding: 100px 40px;
    position: relative;
    margin-top: 20px;
  }

  #quote-left, #quote-right {
    color: yellow;
    font-size: 3em;
    position: absolute;
  }

  #quote-left {
    top: 20px;
    left: 20px;
  }

  #quote-right {
    bottom: 20px;
    right: 20px;
  }

  #quote {
    font-size: 1.5em;
    text-align: center;
  }

  #author {
    position: absolute;
    font-size: 1.1em;
    left: 50px;
    bottom: 30px;
  }

  .btn {
    border-radius: 10px;
    color: yellow;
    border: 1px solid white !important;
    transition: background 0.8s, color 0.8s;
    line-height: 30px;
    margin-top: 30px;
  }

  .btn:hover, .btn:active, .btn:focus {
    color: white !important;
    background-color: yellow !important;
    box-shadow: none;
  }

  ul {
    list-style-type: none;
    padding: 0;
    margin: 10px 0 0 0;
    float: right;
    white-space: nowrap;
    overflow: hidden;
  }

  li {
    display: inline-block;
    margin: 0 0 0 1px;
  }

  #hidden {
    display: none;
  }
Enter fullscreen mode Exit fullscreen mode

现在你的应用程序应该如下所示:
头版

如果仔细查看,您会发现没有显示引号,因此我们必须添加 JavaScript 功能来处理该问题。

— 添加此内容js/app.js

$(document).ready(function () {  
    $("#next-quote").on("click", function (e) {
      e.preventDefault();

      var randomQuoteNumber = getRandomQuoteNumber();
      updateQuote(randomQuoteNumber);
    });

    var q = location.search.split("?q=")[1];

    if (q >= 0 && q < quotes.length) {
      updateQuote(q);
    } else {
      $("#next-quote").click();
    }
  });

  function updateQuote(quoteNumber) {
    var randomQuote = quotes[quoteNumber];

    $("#quote").html(randomQuote.quote);
    $("#author").html(randomQuote.author);
    $("#quote-box").removeClass().addClass("animated bounceIn").one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
      $(this).removeClass();
    });

    $("#share").attr("href", "https://twitter.com/intent/tweet?text=\"" + encodeURIComponent($("#hidden").html(randomQuote.quote).text()) + "\" https://igalafacts.igaladigital.org?q=" + quoteNumber);
  }

  function getRandomQuoteNumber() {
    return Math.floor(Math.random() * quotes.length);
  }

  var quotes = [{"author": "IgalaDigital", "quote": "Did You Know That Ojaina is the place where the Attah's of Igala are burried?"},
{"author": "IgalaDigital", "quote": "Did You Know That the first aircraft that visited the Igala Kingdom landed at Idah in 1955?"},
{"author": "IgalaDigital", "quote": "Did You Know That Attah Ameh Oboni, had seen to the completion of an aerodrome in 1954 at Idah?"},

  {"author": "Ilemona", "quote": "Did you know that the Igala alphabet was adopted from the English alphabet. The latter has five (5) vowels: “a,” “e,” “i,” “o,” “u.”?"},
{"author": "Achimugu Ilemona", "quote": "Did you know the Igala alphabet is made up of thirty-one (31) letters: some vowels, others consonants?"},
{"author": "IgalaDigital", "quote": "Did You Know That Ojaina is a restricted place only allowed for members from the Attah Ruling House?"},
{"author": "IgalaDigital", "quote": "Did you know that Ata Ameh Oboni speak fluently in Igala, Ebira & Hausa?"},
{"author": "Onuche Joseph", "quote": "Did you know that the Ígálá language has seven (7) vowels: “a,” “e,” “ẹ,” “i,” “o,” “ọ,” “u” (encompassing both all the 5 English vowels and two indigenous ones, ‘ẹ’ and  ‘ọ’).?"},

  {"author": "Naomi", "quote": "Did You Know That Idah is also called Idah Alu Ogo Oja Abutu Eje?"},

  {"author": "Inikpi", "quote": "Did you know that Abutu- Eje was the first Igala Ruler?"},
{"author": "IgalaDigital", "quote": "Did you know that you may likely come home to meet one of your family member dead if you kill an animal at Ojaina?"},
{"author": "IgalaDigital", "quote": "Did you know that ata Ameh Oboni took his own life on the night of June 26, 1956?"},
{"author": "IgalaDigital", "quote": "Did you know that the mighty Ata Ameh Oboni died at the age of 51?"},
{"author": "IgalaDigital", "quote": "Did you know that attah Ameh Oboni schooled in Okene(Ebira Land) between 1934 and 1939? Learned in Hausa Literature"},
{"author": "IgalaDigital", "quote": "Did you know that ata Ameh Oboni started off as a market stall tax collector for Idah and Ejule market?"},
{"author": "IgalaDigital", "quote": "Did you know that Ata Obaje Ocheje moved Ameh Oboni from being a market stall tax collector to be come a cheif as onu ugwolawo due to his hard work?"},
{"author": "IgalaDigital", "quote": "Did you know that Ameh Oboni was moved to ankpa from ugwolawo as the judge, commonly known as *Wakali, to be in charge of seven districts?"},
{"author": "IgalaDigital", "quote": "Did you know that Patrick A. Okpanachi, Mallam Garba and Peter Achimugwu were the first in Igala Land that speaks and write in English Language?"},
{"author": "IgalaDigital", "quote": "Did you know that Peter Achimugwu was the man that led the campaign to remove Ameh Oboni as the Attah?"}
]
Enter fullscreen mode Exit fullscreen mode

这只是 JavaScript 基础知识,如果你完全不理解这些内容,可以购买《JavaScript 教师手册》。这本书将教你现代 JavaScript 的所有基础知识和内容。点击 此处Grammar JavaScript获取免费副本。

现在您应该有一个可以显示事实的可运行的应用程序。

功能性应用程序

让我们把它变成 PWA

PWA 的三个基本标准:

  • Web 清单

Web 应用清单是一个 JSON 文件,它会告知浏览器您的渐进式 Web 应用,以及它在安装在用户桌面或移动设备上时的行为方式。典型的清单文件包含应用名称、应用应使用的图标以及应用启动时应打开的 URL。

  • Service Worker
    是一种脚本,允许浏览器在后台独立运行,从而实现无需网页或用户交互的功能。目前,它们已经包含推送通知和后台同步等功能。

  • 图标
    这些图标控制你的应用程序,并针对不同的设备提供不同的尺寸。如果没有它们,你的 PWA 应用将无法运行。

现在让我们开始吧。

在我们继续之前,请确保你正在使用实时服务器
使用(Chrome 的 Web 服务器,或VSCode Live Server

创建以下文件:

sw.js(在根目录中)

manifest.json(在根目录中)

img/icons(我们存储图标的地方

首先,我们需要检查浏览器是否支持服务工作者并注册一个新的。

js/app.js添加

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
   navigator.serviceWorker.register('../sw.js').then( () => {
    console.log('Service Worker Registered')
   })
 })
}
Enter fullscreen mode Exit fullscreen mode

开发工具

开发工具

你的最终结果app.js应该是这样的

$(document).ready(function () {  
    $("#next-quote").on("click", function (e) {
      e.preventDefault();

      var randomQuoteNumber = getRandomQuoteNumber();
      updateQuote(randomQuoteNumber);
    });

    var q = location.search.split("?q=")[1];

    if (q >= 0 && q < quotes.length) {
      updateQuote(q);
    } else {
      $("#next-quote").click();
    }
  });

  function updateQuote(quoteNumber) {
    var randomQuote = quotes[quoteNumber];

    $("#quote").html(randomQuote.quote);
    $("#author").html(randomQuote.author);
    $("#quote-box").removeClass().addClass("animated bounceIn").one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
      $(this).removeClass();
    });

    $("#share").attr("href", "https://twitter.com/intent/tweet?text=\"" + encodeURIComponent($("#hidden").html(randomQuote.quote).text()) + "\" https://igalafacts.igaladigital.org?q=" + quoteNumber);
  }

  function getRandomQuoteNumber() {
    return Math.floor(Math.random() * quotes.length);
  }

  var quotes = [{"author": "IgalaDigital", "quote": "Did You Know That Ojaina is the place where the Attah's of Igala are burried?"},
{"author": "IgalaDigital", "quote": "Did You Know That the first aircraft that visited the Igala Kingdom landed at Idah in 1955?"},
{"author": "IgalaDigital", "quote": "Did You Know That Attah Ameh Oboni, had seen to the completion of an aerodrome in 1954 at Idah?"},

  {"author": "Ilemona", "quote": "Did you know that the Igala alphabet was adopted from the English alphabet. The latter has five (5) vowels: “a,” “e,” “i,” “o,” “u.”?"},
{"author": "Achimugu Ilemona", "quote": "Did you know the Igala alphabet is made up of thirty-one (31) letters: some vowels, others consonants?"},
{"author": "IgalaDigital", "quote": "Did You Know That Ojaina is a restricted place only allowed for members from the Attah Ruling House?"},
{"author": "IgalaDigital", "quote": "Did you know that Ata Ameh Oboni speak fluently in Igala, Ebira & Hausa?"},
{"author": "Onuche Joseph", "quote": "Did you know that the Ígálá language has seven (7) vowels: “a,” “e,” “ẹ,” “i,” “o,” “ọ,” “u” (encompassing both all the 5 English vowels and two indigenous ones, ‘ẹ’ and  ‘ọ’).?"},

  {"author": "Naomi", "quote": "Did You Know That Idah is also called Idah Alu Ogo Oja Abutu Eje?"},

  {"author": "Inikpi", "quote": "Did you know that Abutu- Eje was the first Igala Ruler?"},
{"author": "IgalaDigital", "quote": "Did you know that you may likely come home to meet one of your family member dead if you kill an animal at Ojaina?"},
{"author": "IgalaDigital", "quote": "Did you know that ata Ameh Oboni took his own life on the night of June 26, 1956?"},
{"author": "IgalaDigital", "quote": "Did you know that the mighty Ata Ameh Oboni died at the age of 51?"},
{"author": "IgalaDigital", "quote": "Did you know that attah Ameh Oboni schooled in Okene(Ebira Land) between 1934 and 1939? Learned in Hausa Literature"},
{"author": "IgalaDigital", "quote": "Did you know that ata Ameh Oboni started off as a market stall tax collector for Idah and Ejule market?"},
{"author": "IgalaDigital", "quote": "Did you know that Ata Obaje Ocheje moved Ameh Oboni from being a market stall tax collector to be come a cheif as onu ugwolawo due to his hard work?"},
{"author": "IgalaDigital", "quote": "Did you know that Ameh Oboni was moved to ankpa from ugwolawo as the judge, commonly known as *Wakali, to be in charge of seven districts?"},
{"author": "IgalaDigital", "quote": "Did you know that Patrick A. Okpanachi, Mallam Garba and Peter Achimugwu were the first in Igala Land that speaks and write in English Language?"},
{"author": "IgalaDigital", "quote": "Did you know that Peter Achimugwu was the man that led the campaign to remove Ameh Oboni as the Attah?"}
]
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
   navigator.serviceWorker.register('../sw.js').then( () => {
    console.log('Service Worker Registered')
   })
 })
}
Enter fullscreen mode Exit fullscreen mode

我们将使用 Workbox 库来支持我们的服务工作者

Workbox 是 Google 开发的一组库和 Node 模块,可以轻松缓存资产并充分利用用于构建渐进式 Web 应用程序的功能。

我们的服务工作者的想法是缓存所有文件(字体、JavaScript、CSS、图像等),以便我们可以在页面加载后离线访问它们。

关于Service Worker,需要理解的重点是,您可以掌控网络。您可以决定缓存什么、如何缓存以及如何将缓存的数据返回给用户。

sw.js添加以下内容:

importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js');
if (workbox) {
    console.log("Yay! Workbox is loaded !");
    workbox.precaching.precacheAndRoute([]);
/*  cache images in the e.g others folder; edit to other folders you got
   and config in the sw-config.js file
    */
    workbox.routing.registerRoute(
        /(.*)others(.*)\.(?:png|gif|jpg)/,
        new workbox.strategies.CacheFirst({
            cacheName: "images",
            plugins: [
                new workbox.expiration.Plugin({
                    maxEntries: 50,
                    maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
                })
            ]
        })
    );
    /* Make your JS and CSS âš¡ fast by returning the assets from the cache,
  while making sure they are updated in the background for the next use.
  */
    workbox.routing.registerRoute(
    // cache js, css, scc files
        /.*\.(?:css|js|scss|)/,
        // use cache but update in the background ASAP
        new workbox.strategies.StaleWhileRevalidate({
            // use a custom cache name
            cacheName: "assets",
        })
    );
// cache google fonts
    workbox.routing.registerRoute(
        new RegExp("https://fonts.(?:googleapis|gstatic).com/(.*)"),
        new workbox.strategies.CacheFirst({
            cacheName: "google-fonts",
            plugins: [
                new workbox.cacheableResponse.Plugin({
                    statuses: [0, 200],
                }),
            ],
        })
    );
// add offline analytics
    workbox.googleAnalytics.initialize();
/* Install a new service worker and have it update
and control a web page as soon as possible
*/
workbox.core.skipWaiting();
    workbox.core.clientsClaim();
} else {
    console.log("Oops! Workbox didn't load 👺");
}
Enter fullscreen mode Exit fullscreen mode

现在我们的服务工作者可以工作,并且会在页面加载后缓存文件。

现在让我们让我们的应用程序可安装。

— 添加此内容manifest.json

{
    "name": "Igala Facts",
    "short_name": "Igala Facts",
    "icons": [
      {
        "src": "img/icons/icon-72x72.png",
        "sizes": "72x72",
        "type": "image/png"
      },
      {
        "src": "img/icons/icon-96x96.png",
        "sizes": "96x96",
        "type": "image/png"
      },
      {
        "src": "img/icons/icon-128x128.png",
        "sizes": "128x128",
        "type": "image/png"
      },
      {
        "src": "img/icons/icon-144x144.png",
        "sizes": "144x144",
        "type": "image/png"
      },
      {
        "src": "img/icons/icon-152x152.png",
        "sizes": "152x152",
        "type": "image/png"
      },
      {
        "src": "img/icons/icon-192x192.png",
        "sizes": "192x192",
        "type": "image/png"
      },
      {
        "src": "img/icons/icon-384x384.png",
        "sizes": "384x384",
        "type": "image/png"
      },
      {
        "src": "img/icons/icon-512x512.png",
        "sizes": "512x512",
        "type": "image/png"
      }
    ],
    "start_url": "/index.html",
    "display": "standalone",
    "background_color": "#000",
    "theme_color": "#ffff00"
  }
Enter fullscreen mode Exit fullscreen mode

PWA 图标尺寸应为px和 以下尺寸:72x72,,,,,,,,, 您可以使用Web Manifest Generator生成96x96128x128144x144152x152192x192384x384512x512
manifest.json

在开发工具中显示

现在我们需要将我们的 Web 应用连接到清单,以允许从该页面“添加到主屏幕”。将其添加到您的index.html

<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#333" />
Enter fullscreen mode Exit fullscreen mode

如果您有多个页面,则需要将其添加到所有页面。您也可以使用此处使用的
相同方法theme-colormanifest.json

现在你的最终结果index.html应该是这样的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>The Igala Facts you never knew</title>
    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
    <link href='https://fonts.googleapis.com/css?family=Roboto+Slab:400,700' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.2.3/animate.min.css">
    <link rel="manifest" href="manifest.json" />
  <meta name="theme-color" content="yellow" />
</head>
<body>
    <div class="container">
        <div class="row">
          <div class="col-sm-6">
            <h1><span class="main-color">Random Igala</span><br />Facts</h1>
            <p>The best facts about Igala in one place. You can easily see the best facts and  share the ones you love on twitter with one click.</p>
          </div>
          <div class="col-sm-6">
            <div class="row">
              <div class="col-xs-6">
                <a id="next-quote" class="btn btn-lg btn-default btn-block" href="#"><i class="fa fa-refresh"></i> Next Fact</a>
              </div>
              <div class="col-xs-6">
                <a id="share" class="btn btn-lg btn-default btn-block" href="#" target="_top"><i class="fa fa-twitter"></i> Share</a>
              </div>
            </div>

            <div id="quote-box">
              <i id="quote-left" class="fa fa-quote-left"></i>
              <p id="quote"></p>
              <span id="author" class="main-color"></span>
              <i id="quote-right" class="fa fa-quote-right"></i>
            </div>

            <div class="row">       
              <div class="col-xs-12">
                <ul>
                  <li>Follow Us</li>
                  <li><a class="main-color" href="https://facebook.com/theigaladigital" target="_blank">@theigaladigital</a></li>
                    </ul>
                  </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div id="hidden"></div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
      <script src="js/app.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

恭喜,您已成功将您的网站转变为渐进式 Web 应用程序。

结论

在本文中,我们了解了通过添加清单文件和 Service Worker 构建 PWA 是多么简单快捷,它极大地提升了传统 Web 应用的用户体验。PWA 快速、安全、可靠,而且最重要的是,它们支持离线模式。

现在许多框架都为我们设置了服务工作文件,但是,了解如何使用 Vanilla JavaScript 实现它可以帮助您理解 PWAs。

附言:如果您遇到问题,可能是 HTTPS 的问题。PWA 不支持 HTTP,因此如果您在本地计算机上工作,请确保使用 http-server 或 live-server 运行。

感谢您的阅读!

在TwitterFacebook上关注我,我无处不在@dfiredeveloper

文章来源:https://dev.to/dfiredeveloper/how-to-easily-turn-your-website-to-a-progressive-web-app-pwa-2nm4
PREV
提高 Git 工作效率的 7 个技巧
NEXT
3 个让 CSS 变得简单的网站!