[译]Vue 3, PWA和 service worker

1,429 阅读6分钟

作者:Piotr Ładoński。本文翻译自:dev.to/voodu/vue-3…

最近我开始玩Vue。当然,从“Hello World”计算器开始,有很好的记录的Vue 2不是一个选择,所以我决定在Vue 3中使用简单的PWA。建立一个项目并不像看起来那么容易,所以我将在这里为任何感兴趣的人描述它(并为我自己提供未来的参考)。

我将描述所有的东西,所以希望它对完全初学者有用。我不会解释Vue、PWA或服务人员的哲学——它只是关于设置这些东西。

我正在使用Win10,所以我将从这个PoV描述这个过程(但是,它只对节点安装重要)。

node、npm和Vue

与所有JS项目一样,使用Node&npm更简单。

如果您还没有,我建议您使用nvm安装Node。可能最简单的方法就是到这里,下载最新的nvm-setup.zip,提取并运行安装程序。之后,您应该可以在命令提示符中使用nvm。如果你想安装最新的稳定版本只是去与:

nvm install latest

对于某些特定的版本,您可以执行

nvm install 15.4.0

那么,记得使用哦!

nvm use 15.4.0

对于Node,npm也应该自动安装。对我来说,节点版本是15.4.0,npm是7.3.0。 为了让我们的生活更轻松,还有Vue CLI可以帮助我们建立项目。安装它:

npm install -g @vue/cli

它将允许您从终端使用vue命令。对我来说,vue--version返回@vue/cli4.5.9。 现在,我们可以从我们的迷你项目开始。

创建项目

使用Vue CLI创建新项目非常简单。就跟:

vue create our-app-name

然后使用箭头只需选择选项。我挑了:

手动选择功能

然后选择空格键渐进式Web应用(PWA)支持。按回车键继续,然后选择Vue版本到3. x,ES Lint仅具有防错功能,Lint保存,在专用配置文件中,键入n并按回车键生成项目(需要1-2分钟)。

当然你可以选择不同的选项。只有PWA支持是必要的

运行它

生成的项目可以开箱即用。首先,记得导航到创建的项目文件夹,然后运行开发服务器:

cd our-app-name
npm run serve

输出应提供可以访问生成的应用的地址。对我来说,这是超文本传输协议://localhost: 8080/(如果你想阻止它,只要CTRL+C它) 请注意,当前_Service Worker不工作-如果您在Dev Tools中转到Application>Service Worker,您将看不到它。生成的项目使服务_人员仅在生产构建中活跃。让我们检查一下。 要创建生产构建,请运行

npm run build

给它一些时间,它会在你的项目_文件夹中创建dist_目录。现在你需要把它托管在某个地方。我推荐Chrome的Web Server,因为它非常容易使用,并且工作正常(我也尝试了Python简单的超文本传输协议服务器,但是它对我来说不能正常工作,所以要小心)。只需在服务器中选择您的dist文件夹并运行它。在超文本传输协议://127.0.0.1:8000你应该能够访问你的网站。现在,您可以在Dev Tools的_Application选项_卡中找到有关Service Worker的信息,并查看有关它的一些控制台日志。

驯服 Service Worke

太好了!所有东西都跑起来了!这时又有什么问题呢?当您希望自己使用Service Worker控制缓存并在开发过程中检查它而不需要不断创建生产版本时,就会出现问题。

我现在要展示三样东西:

  1. 如何在开发服务器中运行Service Worker
  2. 如何控制缓存行为
  3. 如何在生产构建中使用外部模块

开发服务器中的SW

警告——默认情况下,SW在开发中被禁用,因为它可能会缓存一些新编辑的scripts/assets,您将无法看到您的更改。记住这一点,如果你不需要它来避免“为什么它不改变?!”问题。

另一个警告——这可能不是最好的方法… 但它的简单和工程:)

案例:我们希望Service Worker在开发模式中处于活动状态,并且能够控制其缓存策略。

不深入细节,让我们实现它。

首先,你需要在你的项目中安装service work rW-webpack-plugin

npm install -D serviceworker-webpack-plugin

然后在你的项目的根(旁边的src文件夹)添加新的文件vue.config.js内容:

// vue.config.js
const path = require("path");
const ServiceWorkerWebpackPlugin = require("serviceworker-webpack-plugin");
module.exports = {
  configureWebpack: {
    plugins: [
      new ServiceWorkerWebpackPlugin({
        entry: path.join(__dirname, "./src/service-worker.js")
      })
    ]
  }
};

并修改src/main.js以包括这些行(在create App之前):

// src/main.js
// other imports...
import runtime from "serviceworker-webpack-plugin/lib/runtime";
if ("serviceWorker" in navigator) {
  runtime.register();
}
// createApp...

最后,在src中添加带有一些Hello world内容的服务worker.js:

// src/service-worker.js
console.log("Hello world from our SW!");

然后运行开发服务器

npm run serve

当您在浏览器中导航到您的应用程序时,您应该会在控制台中看到来自Service-Worker的消息。成功!

控制缓存-Workbox

从头开始写软件可能很有趣… 但是让我们把它变得简单,并使用Workbox。它已经安装,所以您只需要在SW脚本中导入它。我不会解释下面片段中的所有内容,因为它在工作框的入门页上已经非常清楚了。这只是为匹配某些正则表达式(在这种情况下是图像)的数据设置特定规则的例子。

// src/service-worker.js
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
import { Plugin } from 'workbox-expiration';
import { precacheAndRoute } from 'workbox-precaching';
precacheAndRoute(self.serviceWorkerOption.assets);
registerRoute(
    /\.(?:png|gif|jpg|jpeg|svg)$/,
    new StaleWhileRevalidate({
        cacheName: 'images',
        plugins: [
            new Plugin({
                maxEntries: 60,
                maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
            }),
        ],
    })
);

只是简短的评论关于pre ache And Route行-self.serviceWorkerOption.assets来自我们之前安装的service Worker-webpack-plugin,并包含我们应用程序中的所有静态资产。 现在,即使您处于开发模式,您也应该在控制台中看到一些工作框日志。在第一页加载它将是

以及随后类似的事情

如果您在Dev Tools中转到_网络_选项卡并模拟脱机模式,应用程序仍应正常加载。 太棒了!解决了两个问题-我们对我们的服务人员有细粒度的控制,并且它在开发模式下工作。

固定探针上的SW

与此同时,不幸的是,我们搞砸了应用的生产版本。如果您运行npm run build并查看它,一开始可能看起来不错,但事实并非如此。首先,在随后的刷新中,你可以看到新内容可用;请刷新。

日志所有的时间,虽然你不改变任何东西。此外,如果您选中_应用程序_选项卡,您将看到两个服务工作者一直在活动,第二个等待激活。即使你强制更新,刷新后也会有另一个等待。

问题来自双重注册-一个SW注册在main.js,第二个来自生成的registerServiceWorker.js.这是我无法很好地克服的问题,但我想出了两个可以接受的解决方案:

  1. 如果您不关心来自registerServiceWorker.js的日志记录,请不要将其导入src/main.js,问题就会消失。

  2. 如果你想保留这些控制台日志,但是可以让SW只在prod上工作(但是保留对缓存规则的控制),并且在SW中导入模块的方式更加复杂,这需要更多的努力:首先,将vue.config.js内容更改为:

module.exports = {
  pwa: {
    workboxPluginMode: "InjectManifest",
    workboxOptions: {
      swSrc: "src/service-worker.js"
    }
  }
};

然后恢复您在src/main.js中所做的更改(即删除任何与service Worker-webpack-plugin相关的内容)。最后,您需要更改src/service-worker.js使用导入和使用不同参数的前置。如果您想使用一些外部模块,请使用带有CDN链接的import Scripts(例如,下面的动词;用法很愚蠢,但演示了这样做的方式)。注意现在如何展开工作框名称:

importScripts('https://momentjs.com/downloads/moment.min.js');
workbox.precaching.precacheAndRoute(self.__precacheManifest);
const cacheExpTime = moment().add(1, 'day');
const cacheTimeLeft = moment.duration(cacheExpTime.diff(moment())).asSeconds();
workbox.routing.registerRoute(
    /\.(?:png|ico|gif|jpg|jpeg|svg)$/,
    new workbox.strategies.StaleWhileRevalidate({
        cacheName: 'images',
        plugins: [
            new workbox.expiration.Plugin({
                maxEntries: 60,
                maxAgeSeconds: cacheTimeLeft, // 1 day
            }),
        ],
    })
);

当然还有第三个选项,它可以让你继续记录和其他一切,但是我不知道如何正确配置Webpack。如果你有任何简单的解决方案,我会非常乐意在评论中阅读:)

结论

如果您想要非常简单的缓存技术,并且保持只由服务工作者处理静态资产是可以的,那么生成的项目绝对足够了。但是,如果希望对Service Worker进行更多的控制,则可以缓存ex。API调用,您需要以某种方式调整它。我希望上面的提示,如何做到这一点以及如何处理开发模式将是有用的。 如上所述,这绝对不是最好和唯一的解决方案。这只是一些Vue新手(像我)以合理的方式与服务人员打交道的一个初步选择。