vue使用pwa_如何使用HTML,CSS和JavaScript从头开始构建PWA

vue使用pwa

Progressive web apps are a way to bring that native app feeling to a traditional web app. With PWAs we can enhance our website with mobile app features which increase usability and offer a great user experience.

渐进式Web应用程序是一种将本地应用程序的感觉带入传统Web应用程序的方法。 借助PWA,我们可以使用移动应用程序功能来增强我们的网站,这些功能可以提高可用性并提供出色的用户体验。

In this article, we are going to build a PWA from scratch with HTML, CSS, and JavaScript. Here are the topics we'll cover:

在本文中,我们将使用HTML,CSS和JavaScript从头开始构建PWA。 以下是我们将讨论的主题:

So, let's get started with an important question: What the heck is a PWA?

因此,让我们开始一个重要的问题:PWA到底是什么?

什么是渐进式Web应用程序? (What is a Progressive Web App ?)

A Progressive Web App is a web app that delivers an app-like experience to users by using modern web capabilities. In the end, it's just your regular website that runs in a browser with some enhancements. It gives you the ability:

渐进式Web应用程序是一种通过使用现代Web功能向用户提供类似于应用程序的体验的Web应用程序。 最后,只有常规网站才能在带有某些增强功能的浏览器中运行。 它具有以下功能:

  • To install it on a mobile home screen

    要将其安装在移动主屏幕上
  • To access it when offline

    离线访问
  • To access the camera

    存取相机
  • To get push notifications

    获取推送通知
  • To do background synchronization

    执行后台同步

And so much more.

还有更多。

However, to be able to transform our traditional web app to a PWA, we have to adjust it a little bit by adding a web app manifest file and a service worker.

但是,为了能够将传统的Web应用程序转换为PWA,我们必须通过添加Web应用程序清单文件和服务工作者来对其进行一些调整。

Don't worry about these new terms – we'll cover them below.

不用担心这些新术语-我们将在下面介绍它们。

First, we have to build our traditional web app. So let's start with the markup.

首先,我们必须构建传统的Web应用程序。 因此,让我们从标记开始。

标记 (Markup)

The HTML file is relatively simple. We wrap everything in the main tag.

HTML文件相对简单。 我们将所有内容包装在main标签中。

  • In index.html

    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" />
    <link rel="stylesheet" href="css/style.css" />
    <title>Dev'Coffee PWA</title>
  </head>
  <body>
    <main>
      <nav>
        <h1>Dev'Coffee</h1>
        <ul>
          <li>Home</li>
          <li>About</li>
          <li>Blog</li>
        </ul>
      </nav>
      <div class="container"></div>
    </main>
    <script src="js/app.js"></script>
  </body>
</html>

And create a navigation bar with the nav tag. Then, the div with the class .container will hold our cards that we add later with JavaScript.

并使用nav标签创建一个导航栏。 然后,类为.containerdiv将保存我们的卡,稍后我们将使用JavaScript添加它们。

Now that we've gotten that out of the way, let's style it with CSS.

现在我们已经解决了这个问题,让我们使用CSS对其进行样式设置。

造型 (Styling)

Here, as usual, we start by importing the fonts we need. Then we'll do some resets to prevent the default behavior.

在这里,像往常一样,我们从导入所需的字体开始。 然后,我们将进行一些重置以防止默认行为。

  • In css/style.css

    css/style.css

@import url("https://fonts.googleapis.com/css?family=Nunito:400,700&display=swap");
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  background: #fdfdfd;
  font-family: "Nunito", sans-serif;
  font-size: 1rem;
}
main {
  max-width: 900px;
  margin: auto;
  padding: 0.5rem;
  text-align: center;
}
nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
ul {
  list-style: none;
  display: flex;
}

li {
  margin-right: 1rem;
}
h1 {
  color: #e74c3c;
  margin-bottom: 0.5rem;
}

Then, we limit the main element's maximum width to 900px to make it look good on a large screen.

然后,我们将main元素的最大宽度限制为900px以使其在大屏幕上看起来不错。

For the navbar, I want the logo to be at the left and the links at the right. So for the nav tag, after making it a flex container, we use justify-content: space-between; to align them.

对于导航栏,我希望徽标位于左侧,链接位于右侧。 因此,对于nav标签,在将其设为flex容器后,我们使用justify-content: space-between; 对齐它们。

  • In css/style.css

    css/style.css

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  grid-gap: 1rem;
  justify-content: center;
  align-items: center;
  margin: auto;
  padding: 1rem 0;
}
.card {
  display: flex;
  align-items: center;
  flex-direction: column;
  width: 15rem auto;
  height: 15rem;
  background: #fff;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
  border-radius: 10px;
  margin: auto;
  overflow: hidden;
}
.card--avatar {
  width: 100%;
  height: 10rem;
  object-fit: cover;
}
.card--title {
  color: #222;
  font-weight: 700;
  text-transform: capitalize;
  font-size: 1.1rem;
  margin-top: 0.5rem;
}
.card--link {
  text-decoration: none;
  background: #db4938;
  color: #fff;
  padding: 0.3rem 1rem;
  border-radius: 20px;
}

We'll have several cards, so for the container element it will be displayed as a grid. And, with grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)), we can now make our cards responsive so that they use at least 15rem width if there is enough space (and 1fr if not).

我们将有几张卡片,因此对于容器元素,它将显示为网格。 并且,随着grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr))现在我们可以让我们的卡响应,使他们至少使用15rem宽度,如果有足够的空间(和1fr如果没有)。

And to make them look nice we double the shadow effect on the .card class and use object-fit: cover on .card--avatar to prevent the image from stretching.

为了使它们看起来更好,我们将.card类上的阴影效果加倍,并使用object-fit: cover .card--avatar上的.card--avatar防止图像拉伸。

Now it looks much better – but we still don't have data to show.

现在看起来好多了-但我们仍然没有数据可以显示。

Let's fix it in the next section

让我们在下一节中修复它

使用JavaScript显示数据 (Show data with JavaScript)

Notice that I used large images that take some time to load. This will show you in the best way the power of service workers.

请注意,我使用的大图像需要花费一些时间才能加载。 这将以最佳方式向您显示服务人员的力量。

As I said earlier, the .container class will hold our cards. Therefore, we need to select it.

正如我之前说的, .container类将持有我们的卡。 因此,我们需要选择它。

  • In js/app.js

    js/app.js

const container = document.querySelector(".container")
const coffees = [
  { name: "Perspiciatis", image: "images/coffee1.jpg" },
  { name: "Voluptatem", image: "images/coffee2.jpg" },
  { name: "Explicabo", image: "images/coffee3.jpg" },
  { name: "Rchitecto", image: "images/coffee4.jpg" },
  { name: " Beatae", image: "images/coffee5.jpg" },
  { name: " Vitae", image: "images/coffee6.jpg" },
  { name: "Inventore", image: "images/coffee7.jpg" },
  { name: "Veritatis", image: "images/coffee8.jpg" },
  { name: "Accusantium", image: "images/coffee9.jpg" },
]

Then, we create an array of cards with names and images.

然后,我们创建一个包含名称和图像的卡片阵列。

  • In js/app.js

    js/app.js

const showCoffees = () => {
  let output = ""
  coffees.forEach(
    ({ name, image }) =>
      (output += `
              <div class="card">
                <img class="card--avatar" src=${image} />
                <h1 class="card--title">${name}</h1>
                <a class="card--link" href="#">Taste</a>
              </div>
              `)
  )
  container.innerHTML = output
}

document.addEventListener("DOMContentLoaded", showCoffees)

With this code above, we can now loop through the array and show them on the HTML file. And to make everything work, we wait until the DOM (Document Object Model) content finishes loading to run the showCoffees method.

有了上面的代码,我们现在可以遍历数组并将其显示在HTML文件中。 为了使一切正常,我们要等到DOM(文档对象模型)内容完成加载后才能运行showCoffees方法。

We've done a lot, but for now, we just have a traditional web app. So, let's change that in the next section by introducing some PWA features.

我们做了很多事情,但是到目前为止,我们只有一个传统的Web应用程序。 因此,让我们在下一部分中通过介绍一些PWA功能来更改它。

Web App清单 (Web App Manifest)

The web app manifest is a simple JSON file that informs the browser about your web app. It tells how it should behave when installed on the user's mobile device or desktop. And to show the Add to Home Screen prompt, the web app manifest is required.

Web应用程序清单是一个简单的JSON文件,用于通知浏览器您的Web应用程序。 它说明了将其安装在用户的移动设备或台式机上时的行为。 为了显示“添加到主屏幕”提示,需要Web应用程序清单。

Now that we know what a web manifest is, let's create a new file named manifest.json (you have to name it like that) in the root directory. Then add this code block below.

现在我们知道了Web清单是什么,让我们在根目录中创建一个名为manifest.json的新文件(您必须这样命名)。 然后在下面添加此代码块。

  • In manifest.json

    manifest.json

{
  "name": "Dev'Coffee",
  "short_name": "DevCoffee",
  "start_url": "index.html",
  "display": "standalone",
  "background_color": "#fdfdfd",
  "theme_color": "#db4938",
  "orientation": "portrait-primary",
  "icons": [
    {
      "src": "/images/icons/icon-72x72.png",
      "type": "image/png", "sizes": "72x72"
    },
    {
      "src": "/images/icons/icon-96x96.png",
      "type": "image/png", "sizes": "96x96"
    },
    {
      "src": "/images/icons/icon-128x128.png",
      "type": "image/png","sizes": "128x128"
    },
    {
      "src": "/images/icons/icon-144x144.png",
      "type": "image/png", "sizes": "144x144"
    },
    {
      "src": "/images/icons/icon-152x152.png",
      "type": "image/png", "sizes": "152x152"
    },
    {
      "src": "/images/icons/icon-192x192.png",
      "type": "image/png", "sizes": "192x192"
    },
    {
      "src": "/images/icons/icon-384x384.png",
      "type": "image/png", "sizes": "384x384"
    },
    {
      "src": "/images/icons/icon-512x512.png",
      "type": "image/png", "sizes": "512x512"
    }
  ]
}

In the end, it's just a JSON file with some mandatory and optional properties.

最后,它只是一个带有一些必需和可选属性的JSON文件。

name: When the browser launches the splash screen, it will be the name displayed on the screen.

名称:浏览器启动初始屏幕时,它将是屏幕上显示的名称。

short_name: It will be the name displayed underneath your app shortcut on the home screen.

short_name:它将是显示在主屏幕上您应用快捷方式下方的名称。

start_url: It will be the page shown to the user when your app is open.

start_url:打开您的应用后,它将显示给用户。

display: It tells the browser how to display the app. There are several modes like minimal-ui, fullscreen, browser etc. Here, we use the standalone mode to hide everything related to the browser.

display:告诉浏览器如何显示应用程序。 有几种模式,如minimal-uifullscreenbrowser等。在这里,我们使用standalone模式隐藏与浏览器相关的所有内容。

background_color: When the browser launches the splash screen, it will be the background of the screen.

background_color:当浏览器启动初始屏幕时,它将是屏幕的背景。

theme_color: It will be the background color of the status bar when we open the app.

theme_color:这是我们打开应用程序时状态栏的背景色。

orientation: It tells the browser the orientation to have when displaying the app.

方向:它告诉浏览器显示应用程序时的方向。

icons: When the browser launches the splash screen, it will be the icon displayed on the screen. Here, I used all sizes to fit any device's preferred icon. But you can just use one or two. It's up to you.

图标:当浏览器启动启动屏幕时,它将是屏幕上显示的图标。 在这里,我使用了所有尺寸以适合任何设备的首选图标。 但是您只能使用一两个。 由你决定。

Now that we have a web app manifest, let's add it to the HTML file.

现在我们有了一个Web应用程序清单,让我们将其添加到HTML文件中。

  • In index.html (head tag)

    index.html (头标记)

<link rel="manifest" href="manifest.json" />
<!-- ios support -->
<link rel="apple-touch-icon" href="images/icons/icon-72x72.png" />
<link rel="apple-touch-icon" href="images/icons/icon-96x96.png" />
<link rel="apple-touch-icon" href="images/icons/icon-128x128.png" />
<link rel="apple-touch-icon" href="images/icons/icon-144x144.png" />
<link rel="apple-touch-icon" href="images/icons/icon-152x152.png" />
<link rel="apple-touch-icon" href="images/icons/icon-192x192.png" />
<link rel="apple-touch-icon" href="images/icons/icon-384x384.png" />
<link rel="apple-touch-icon" href="images/icons/icon-512x512.png" />
<meta name="apple-mobile-web-app-status-bar" content="#db4938" />
<meta name="theme-color" content="#db4938" />

As you can see, we linked our manifest.json file to the head tag. And add some other links which handle the iOS support to show the icons and colorize the status bar with our theme color.

如您所见,我们将manifest.json文件链接到head标签。 并添加其他一些处理iOS支持的链接,以显示图标并使用我们的主题颜色为状态栏着色。

With that, we can now dive into the final part and introduce the service worker.

这样,我们现在可以深入探讨最后一部分并介绍服务人员。

什么是服务人员? (What is a Service Worker?)

Notice that PWAs run only on https because the service worker can access the request and handle it. Therefore security is required.

请注意,由于服务工作者可以访问并处理请求,因此PWA仅在https上运行。 因此,需要安全性。

A service worker is a script that your browser runs in the background in a separate thread. That means it runs in a different place and is completely separate from your web page. That's the reason why it can't manipulate your DOM element.

服务工作者是一个脚本,您的浏览器在后台在单独的线程中运行。 这意味着它在其他位置运行,并且与您的网页完全分开。 这就是为什么它无法操纵DOM元素的原因。

However, it's super powerful. The service worker can intercept and handle network requests, manage the cache to enable offline support or send push notifications to your users.

但是,它超级强大。 服务人员可以拦截和处理网络请求,管理缓存以启用脱机支持或向您的用户发送推送通知。

S0 let's create our very first service worker in the root folder and name it serviceWorker.js (the name is up to you). But you have to put it in the root so that you don't limit its scope to one folder.

S0让我们在根文件夹中创建第一个服务工作者,并将其命名为serviceWorker.js (名称由您决定)。 但是您必须将其放在根目录中,以免将其范围限制为一个文件夹。

缓存资产 (Cache the assets)

  • In serviceWorker.js

    serviceWorker.js

const staticDevCoffee = "dev-coffee-site-v1"
const assets = [
  "/",
  "/index.html",
  "/css/style.css",
  "/js/app.js",
  "/images/coffee1.jpg",
  "/images/coffee2.jpg",
  "/images/coffee3.jpg",
  "/images/coffee4.jpg",
  "/images/coffee5.jpg",
  "/images/coffee6.jpg",
  "/images/coffee7.jpg",
  "/images/coffee8.jpg",
  "/images/coffee9.jpg",
]

self.addEventListener("install", installEvent => {
  installEvent.waitUntil(
    caches.open(staticDevCoffee).then(cache => {
      cache.addAll(assets)
    })
  )
})

This code looks intimidating first but it just JavaScript (so don't worry).

该代码首先看起来令人生畏,但它只是JavaScript(因此不用担心)。

We declare the name of our cache staticDevCoffee and the assets to store in the cache. And to perform that action, we need to attach a listener to self.

我们声明缓存的名称staticDevCoffee以及要存储在缓存中的资产。 为了执行该操作,我们需要将一个侦听器附加到self

self is the service worker itself. It enables us to listen to life cycle events and do something in return.

self是服务工作者本身。 它使我们能够听取生命周期事件并做些回报。

The service worker has several life cycles, and one of them is the install event. It runs when a service worker is installed. It's triggered as soon as the worker executes, and it's only called once per service worker.

服务人员有多个生命周期,其中之一就是install事件。 它在安装Service Worker时运行。 工作程序执行后立即触发,每个服务工作程序仅调用一次。

When the install event is fired, we run the callback which gives us access to the event object.

install事件被触发时,我们运行回调,使我们可以访问event对象。

Caching something on the browser can take some time to finish because it's asynchronous.

在浏览器上缓存内容可能需要一些时间才能完成,因为它是异步的。

So to handle it, we need to use waitUntil() which, as you might guess, waits for the action to finish.

因此,要处理它,我们需要使用waitUntil() ,您可能会猜到它等待动作完成。

Once the cache API is ready, we can run the open() method and create our cache by passing its name as an argument to caches.open(staticDevCoffee).

缓存API准备就绪后,我们可以运行open()方法并通过将其名称作为参数传递给caches.open(staticDevCoffee)来创建缓存。

Then it returns a promise, which helps us store our assets in the cache with cache.addAll(assets).

然后,它返回一个promise,这有助于我们使用cache.addAll(assets)将资产存储在缓存中。

Hopefully, you're still with me.

希望你还和我在一起。

Now, we've successfully cached our assets in the browser. And the next time we load the page, the service worker will handle the request and fetch the cache if we are offline.

现在,我们已经成功地在浏览器中缓存了我们的资产。 下次我们加载页面时,如果我们处于脱机状态,则服务工作者将处理该请求并获取缓存。

So, let's fetch our cache.

因此,让我们获取缓存。

取得资产 (Fetch the assets)

  • In serviceWorker.js

    serviceWorker.js

self.addEventListener("fetch", fetchEvent => {
  fetchEvent.respondWith(
    caches.match(fetchEvent.request).then(res => {
      return res || fetch(fetchEvent.request)
    })
  )
})

Here, we use the fetch event to, well, get back our data. The callback gives us access to fetchEvent. Then we attach respondWith() to prevent the browser's default response. Instead it returns a promise because the fetch action can take time to finish.

在这里,我们使用fetch事件获取数据。 回调使我们可以访问fetchEvent 。 然后,我们附加respondWith()来防止浏览器的默认响应。 相反,它会返回一个Promise,因为获取操作可能需要一些时间才能完成。

And once the cache ready, we apply the caches.match(fetchEvent.request). It will check if something in the cache matches fetchEvent.request. By the way, fetchEvent.request is just our array of assets.

一旦缓存准备就绪,我们将应用caches.match(fetchEvent.request) 。 它将检查缓存中是否有与fetchEvent.request匹配的fetchEvent.request 。 顺便说一句, fetchEvent.request只是我们的资产数组。

Then, it returns a promise. And finally, we can return the result if it exists or the initial fetch if not.

然后,它返回一个承诺。 最后,我们可以返回结果(如果存在)或初始获取(如果不存在)。

Now, our assets can be cached and fetched by the service worker which increases the load time of our images quite a bit.

现在,服务人员可以缓存和获取我们的资产,这大大增加了图像的加载时间。

And most important, it makes our app available in offline mode.

最重要的是,它使我们的应用程序可以离线使用。

But a service worker alone can't do the job. We need to register it in our project.

但是仅服务人员无法完成这项工作。 我们需要在我们的项目中注册它。

注册服务人员 (Register the Service Worker)

  • In js/app.js

    js/app.js

if ("serviceWorker" in navigator) {
  window.addEventListener("load", function() {
    navigator.serviceWorker
      .register("/serviceWorker.js")
      .then(res => console.log("service worker registered"))
      .catch(err => console.log("service worker not registered", err))
  })
}

Here, we start by checking if the serviceWorker is supported by the current browser (as it's still not supported by all browsers).

在这里,我们首先检查当前浏览器是否支持serviceWorker (因为并非所有浏览器都支持它)。

Then, we listen to the page load event to register our service worker by passing the name of our file serviceWorker.js to navigator.serviceWorker.register() as a parameter to register our worker.

然后,通过将文件serviceWorker.js的名称传递给navigator.serviceWorker.register()作为注册我们的工作人员的参数,我们侦听页面加载事件以注册我们的服务工作人员。

With this update, we have now transformed our regular web app to a PWA.

通过此更新,我们现在将常规网络应用程序转换为PWA。

最后的想法 (Final thoughts)

Throughout this article, we have seen how amazing PWAs can be. By adding a web app manifest file and a service worker, it really improves the user experience of our traditional web app. This is because PWAs are fast, secure, reliable, and – most importantly – they support offline mode.

在本文中,我们已经看到了惊人的PWA。 通过添加Web应用程序清单文件和服务工作者,确实可以改善我们传统Web应用程序的用户体验。 这是因为PWA快速,安全,可靠,而且最重要的是,它们支持脱机模式。

Many frameworks out there now come with a service worker file already set-up for us. But knowing how to implement it with Vanilla JavaScript can help you understand PWAs.

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

And you can go even further with service workers by caching assets dynamically or limiting the size of your cache and so on.

通过动态缓存资产或限制缓存大小等,您可以与服务工作者一起走得更远。

Thanks for reading this article.

感谢您阅读本文。

You can check it out live here and the source code is here.

您可以在此处现场查看 ,源代码在此处

Read more of my articles on my blog

我的博客上阅读更多文章

下一步 (Next steps)

Web Manifest Documentation

Web清单文档

Service Worker Documentation

服务人员文档

Web Manifest Generator

Web清单生成器

Browser Support

浏览器支持

翻译自: https://www.freecodecamp.org/news/build-a-pwa-from-scratch-with-html-css-and-javascript/

vue使用pwa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值