发布于 2026-01-06 1 阅读
0

PWA:构建可离线使用的可安装 Next.js 应用,服务人员的瑞士军刀。

PWA:构建可离线使用的可安装 Next.js 应用

一款专为服务人员设计的瑞士军刀。

让我们构建并转换一个简单的 Nextjs 网站到渐进式 Web 应用程序 (PWA)。

但什么是 PWA?

根据 MDN 网络文档,渐进式 Web 应用 (PWA) 是一种使用 Web 平台技术构建的应用,但它提供的用户体验与平台特定(或原生)应用类似。

这意味着,只需为您的网站编写一段代码,即可使其可在 Android、iOS 或 Windows 等不同设备上安装。

GitHub、Mozilla、福布斯等众多大公司都采用了这种 PWA 技术。

GitHub 上的 PWA

你可能会疑惑,为什么这些公司要创建一个可安装的网站,而他们的工程师却能构建(世界一流的)原生应用程序。

事实上,PWA 的功能远不止将你的网站安装成一个应用程序,它还能提供更多功能。让我们来谈谈这些优势。

渐进式 Web 应用 (PWA) 的优势

  • 它可以离线运行,也可以在后台运行。
  • 它是可安装的,因此与开发原生应用相比,您可以节省资金。
  • 它只需一套代码库即可在不同的设备上运行。
  • 它速度很快,比传统网站或移动应用都要快。
  • 它会自动引导访客安装应用程序,无需额外设置。
  • 以及其他许多人

鉴于以上种种优势,建议将网站转换为 PWA。GitHub 拥有移动应用和桌面应用,但该公司仍在充分利用渐进式 Web 应用 (PWA) 的优势。

为 Next.js 网站设置 PWA 非常简单,只需几分钟即可完成。让我们开始吧!

本教程中我将用到以下工具:

  • Next.js 14.2(应用目录)
  • TypeScript
  • Tailwind CSS
  • 服务包

以下是本教程中我们将要演示的内容。

好的,我们继续。

你可能熟悉前 3 个,但可能不熟悉Serwistpackage。

请在 GitHub 上查看:

GitHub 标志 serwist / serwist

一款专为服务人员设计的瑞士军刀。




Serwist软件包使我们能够将 Nextjs 网站转换为渐进式 Web 应用程序,而无需任何昂贵的配置,同时如果您想充分利用 PWA,它仍然留有进一步配置的空间。

但是标准的 Serwist 配置非常有效,这也是我将在本教程中介绍的内容,之后您可以继续阅读软件包文档以进行进一步的配置。

值得注意的是,Serwist 不仅适用于 Nextjs,也适用于 Svelte 等其他框架。

如何将 Next.js 网站转换为渐进式 Web 应用

步骤 1:构建 Next.js 应用

您可以使用任何现有的 Nextjs 项目,或者使用 Bootstrap 创建一个新yarn create next-app项目npx create-next-app

选择页面目录还是应用目录都无所谓,都可以。

如果你的 Nextjs 应用已经启动并运行,那么我们进入下一步。

步骤 2:为 PWA 安装 Serwist 软件包

在终端中运行以下命令,从 Serwist 安装我们需要的所有软件包。

对于 NPM:npm i @serwist/next && npm i -D serwist
YARN:yarn add @serwist/next && yarn add -D serwist

在继续之前,您可能想知道为什么选择 Serwist?

因为它功能强大。它有助于完成繁重的服务工作进程配置,而且该软件包至今仍在维护。

还有其他类似的 PWA 软件包next-pwa,但我并不推荐,因为该软件包上次更新是在两年前……两年过去了,很多事情都发生了变化。

所以瑟维斯特是天选之人。

步骤 3:配置网站的清单文件

在公共文件夹或应用文件夹中创建一个名为 . 的新文件manifest.json。我们需要将您的应用元数据放在这里。

Web 应用清单文件(通常manifest.json简称为清单文件)是一个包含网站元数据的文件。虽然大多数情况下我们并不关心这个文件,但要让您的 Next.js PWA 应用正常运行,正确配置该文件至关重要manifest.json

市面上有很多 Web 应用程序清单生成器可供使用,例如 Simicart 的这款(点击生成您自己的清单)。

生成 JSON 文件后,将 Metadata 代码复制到 manifest.json 文件中。

您的应用需要图标,无需自行创建,只需下载压缩包即可。下载完成后,解压文件,然后复制其中生成的 4 张图片用于您的项目。

请注意,您复制到项目中的图标必须在 manifest.json 文件中可访问,否则 PWA 可能无法正常工作。

但这还不是全部。

manifest.json 文件必须具有唯一的 ID,这样来自网站 A 的缓存文件就不会与来自网站 B 的文件混淆。

请将以下内容更新到 manifest.json 文件中:

// manifest.json

   "id": "your-unique-id",
    "dir": "ltr",
    "lang": "en",
    "categories": [
      "business",
      "food",
      "shopping"
    ], //app categories
    "prefer_related_applications": false,
  "iarc_rating_id": "13", // minimum age of your prospective users
Enter fullscreen mode Exit fullscreen mode

步骤 4:在您的应用中注册 manifest.json 文件

目前,您的 manifest.json 文件是正确的,但您的应用程序还无法识别它。

要注册它,我们只需要告诉 Next.js 我们拥有它。我们将使用 Next.js 的元数据。

打开src文件夹,找到并打开app文件夹,在layout.tsx文件中,在导出 RootLayout 之前添加以下代码:

export const metadata: Metadata = {
  metadataBase: new URL(your base url"), // use a correct url otherwise your app won’t build
  title: "title of your app",
  description: "your app description here",
  category: "website",
  generator: "Next.js", // framework used

// the big is here 
  manifest: "/manifest.json", 
}
Enter fullscreen mode Exit fullscreen mode

在本教程中,我们只关注manifest.json文件的注册。如有时间,您可以进一步添加元数据,并在线查找相关设置方法。

我们快完成了。

步骤 5:设置 Service Worker 文件

Service Worker 是 PWA 的核心,但很遗憾,本教程并非着重讲解 Service Worker。如需了解更多关于 Service Worker 的信息,请参阅这篇有用的文章。

现在src创建一个名为“service-worker”的新文件夹,并在其中创建一个名为“app-worker.ts

名称可以是任何内容,父文件夹不能放在任何位置,例如,不能放在公共文件夹中,但最好放在或srcpublic

将以下代码放入app-worker.ts文件中:


import { defaultCache } from "@serwist/next/worker";
import type { PrecacheEntry, SerwistGlobalConfig } from "serwist";
import { Serwist } from "serwist";

// This declares the value of `injectionPoint` to TypeScript.
// `injectionPoint` is the string that will be replaced by the
// actual precache manifest. By default, this string is set to
// `"self.__SW_MANIFEST"`.
declare global {
  interface WorkerGlobalScope extends SerwistGlobalConfig {
    __SW_MANIFEST: (PrecacheEntry | string)[] | undefined;
  }
}

declare const self: ServiceWorkerGlobalScope;

const serwist = new Serwist({
  precacheEntries: self.__SW_MANIFEST,
  skipWaiting: true,
  clientsClaim: true,
  navigationPreload: true,
  runtimeCaching: defaultCache,
  fallbacks: {
    entries: [
      {
        url: '/offline', // the page that'll display if user goes offline
        matcher({ request }) {
          return request.destination === 'document';
        },
      },
    ],
  },
});

serwist.addEventListeners();
Enter fullscreen mode Exit fullscreen mode

这段代码直接来自教程serwist,因此建议查阅教程文档以了解其运行原理。

现在你会看到一个 TypeScript 错误,要解决这个问题,请在tsconfig.json以下代码下方添加这段代码target: es5

 "lib": ["dom", "dom.iterable", "esnext", "webworker"],
    "types": ["@serwist/next/typings"],
Enter fullscreen mode Exit fullscreen mode

这个错误本应该被修复。

PS:我把service-worker文件夹、manifest.json 文件和图标都放在了 public 文件夹里。我的文件夹结构如下:

文件结构

步骤 6:重新配置您的Next.config.js文件

该文件位于根目录下,我假设该目录下没有任何文件。如果是这样,请清空该目录下的所有内容,然后放入以下代码:

const {
  PHASE_DEVELOPMENT_SERVER,
  PHASE_PRODUCTION_BUILD,
} = require("next/constants");

/** @type {(phase: string, defaultConfig: import("next").NextConfig) => Promise<import("next").NextConfig>} */
module.exports = async (phase) => {
  /** @type {import("next").NextConfig} */

// Your current or future configuration 

  const nextConfig = {

  };

  if (phase === PHASE_DEVELOPMENT_SERVER || phase === PHASE_PRODUCTION_BUILD) {
    const withSerwist = (await import("@serwist/next")).default({
      swSrc: "src/service-worker/app-worker.ts",
      swDest: "public/sw.js",
      reloadOnOnline: true,
    });
    return withSerwist(nextConfig);
  }

  return nextConfig;
};
Enter fullscreen mode Exit fullscreen mode

这里有几点需要注意。

const nextConfig = {}如果已有 Nextjs 配置,可以在对象中放入;否则,可以将对象留空。

接下来会检查你是否正在进行开发或者你是否已经构建了项目,如果是,Serwist 将发挥其魔力。

我们还需要注意该对象中的以下 3 个方面:

  • swSrc: "src/service-worker/app-worker.ts",
  • swDest: "public/sw.js",
  • 在线重新加载:true,

第一个很简单,那就是我们之前设置的 Service Worker 配置的位置。再次提醒,请确保您正确访问了该路径。

第二个位置是生成的 Service Worker 代码的存放位置,在本例中,它位于 public 文件夹中。

最后一个选项只是询问用户在网络连接正常时是否重新加载页面。例如,用户可能离线访问您的应用,而当网络连接恢复后,启用此选项true将尝试从服务器获取网站内容,而不是从缓存存储中获取。

最后一步:构建并测试您的应用

如果一切设置正确,现在可以通过运行yarn build以下命令来构建您的项目:npm run build

构建成功后,检查您的公共文件夹,您应该会看到一个名为 的新文件sw.js,其中包含一些随机的压缩代码,请勿编辑任何内容。

您现在已将 Nextjs 网站转换为 PWA,用户可以将其安装为应用程序。

将项目部署到您选择的托管服务提供商,一切就绪。

当您访问您的网站时,如果看到如下所示的“安装…”提示,则表明您的 PWA 功能正在运行:

PWA 运行正常

如果你能看到这一点,那就太棒了!

别忘了,Service Worker 还能实现更多功能,例如推送通知等,请尝试阅读更多关于 Service Worker 和 PWA 技术的内容。

在离开之前,我想谈谈将 Nextjs 网站转换为 PWA 时常见的错误和解决方法。

无法安装 next-pwa 或 serwist 软件包

请确保您的应用程序未在本地服务器上运行,如果正在运行,请按 CTRL C 停止它。

node_modules使用 SHIFT + DELETE永久删除文件。

运行yarn install或重新安装您的应用程序包和依赖项npm install

最后,再次安装 serwist 软件包。

所有步骤都正确完成了,但 PWA 仍然无法运行。

可能是你的 manifest.json 文件没有访问到图标的正确路径。如果是这种情况,最稳妥的解决方法是将这些图标移动到 public 文件夹。

请注意,您可以通过简单地以 / 开头来访问公共文件夹中的项目,例如,要访问公共文件夹中的图像文件夹,您需要执行以下操作:/images/…

感谢阅读。

如果这篇文章对您有帮助,请不要忘记分享给其他人。

文章来源:https://dev.to/stephengade/pwa-build-installable-nextjs-app-that-works-offline-3fff