13

我正在使用 Next.js 开发一个服务器端渲染网站,我想让它成为一个渐进式 Web 应用程序,但问题是我找不到让它正确发生的方法。

当我构建应用程序时,它正确地为服务工作者提供服务,但没有 manifest.json 并且在某些项目示例中它为 manifest.json 提供服务,但我在 Lighthouse 审计中尝试了它,它说

Service Worker 没有成功地为 manifest 的 start_url 提供服务

我使用的示例之一使用 Service Worker Precache 创建下一个应用程序

我认为问题在于 start_url 是 . 或 / 不是一个有效的文件,因为在 Next.js 中没有 index.html 从一开始就提供服务。

总之,我正在寻找一个使用 Next.js 将其构建到 dist 文件夹的示例,并且当我提供它时,它具有有效的 Service Worker 和有效的 Web Manifest。

4

2 回答 2

16

A. 一些文件预计会在“/”找到

您遇到此错误是因为浏览器希望从服务器的根目录提供一些文件,包括:

  1. /manifest.json
  2. /sitemap.xml
  3. /favicon.ico
  4. /robots.txt
  5. /browserconfig.xml
  6. /site.webmanifest

虽然这些路径中的大多数都可以使用元标记设置,但旧版浏览器会忽略它们,如果没有提供这些确切的文件名,则会出错。

B. 配置备用路径并使用 NextJS 静态文件

在撰写本文时,NextJS的离线支持工作正在进行中。但它还没有准备好。

如果您不需要支持旧版浏览器并且不需要高级 SEO,则可以使用 NextJS 的Head组件(请参阅文档)来定义manifest.json路径,就像对任何 NextJS 静态文件一样:

import Head from "next/head"

export default () => (
    <Head>
        <link rel="manifest" href="/static/manifest.json" />
        <link rel="manifest" href="/static/site.webmanifest" />
        <link rel="shortcut icon" href="/static/favicon.ico"
    </Head>
)

请注意,robots.txt不能从子目录(source)提供服务,因此如果您需要定义此文件,此解决方案不适合。

C. 按预期提供这些文件

正确的解决方案是像这样从您的快速服务器提供这些文件

const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const { join } = require('path')

const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare()
  .then(() => {
    createServer((req, res) => {
      const parsedUrl = parse(req.url, true)
      const rootStaticFiles = [
        '/manifest.json',
        '/sitemap.xml',
        '/favicon.ico',
        '/robots.txt',
        '/browserconfig.xml',
        '/site.webmanifest',
      ]
      if (rootStaticFiles.indexOf(parsedUrl.pathname) > -1) {
        const path = join(__dirname, 'static', parsedUrl.pathname)
        app.serveStatic(req, res, path)
      } else {
        handle(req, res, parsedUrl)
      }
    })
      .listen(port, (err) => {
        if (err) throw err
        console.log(`> Ready on http://localhost:${port}`)
      })
  })

注意:此代码直接来自NextJS 示例存储库

于 2018-09-09T12:00:30.103 回答
0

以下是使您的 next.js 渐进式的步骤。检查示例

  • npm i next-pwa
  • 下一个.config.json
    const withPWA = require("next-pwa");
    module.exports = withPWA({
      pwa: {
        dest: "public",
        
      },
      ...
    });
  • 从示例中将 manifest.json 和图标添加到公用文件夹。但是,图标目录缺少“maskable_icon.png”。因此,从此处创建一个可屏蔽图标,然后将其添加到“manifest.json”。

     {
        "src": "path/to/maskable_icon.png",
        "sizes": "196x196",
        "type": "image/png",
        "purpose": "any maskable"
      }
    
  • 将这些标签添加到import Head from "next/head". Head用于更好的 SEO 设置。检查文档*

      <meta charSet="utf-8" />
      <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
      <meta
        name="viewport"
        content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
      />
      <meta name="description" content="Description" />
      <meta name="keywords" content="Keywords" />
      <title>Next.js PWA Example</title>
    
      <link rel="manifest" href="/manifest.json" />
      <link
        href="/icons/favicon-16x16.png"
        rel="icon"
        type="image/png"
        sizes="16x16"
      />
      <link
        href="/icons/favicon-32x32.png"
        rel="icon"
        type="image/png"
        sizes="32x32"
      />
      <link rel="apple-touch-icon" href="/apple-icon.png"></link>
      <meta name="theme-color" content="#317EFB" />
    </Head>
    
  • 最后检查它是否工作。从 chrome 应用商店将 Lighthouse 扩展添加到 chrome 开发工具并运行启动性能。

于 2021-03-01T06:52:05.513 回答