我正在使用Next.js开发一个服务器端渲染网站,我想让它成为一个渐进式Web应用程序,但问题是我无法找到使其正确发生的方法。
当我构建应用程序时,它正确地服务于服务工作者,但是没有manifest.json,并且在一些项目示例中它提供了manifest.json,但我在Lighthouse审计中尝试了它,它说
服务工作者未成功提供清单的start_url
我使用Create Next App With Service Worker Precache的一个例子
我认为问题在于start_url是。或/和不是有效的文件,因为在Next.js中没有index.html从一开始就提供服务。
总而言之,我正在寻找一个使用Next.js将其构建到dist文件夹的示例,当我提供它时,它有一个有效的Service Worker和一个有效的Web Manifest。
您有此错误,因为浏览器希望从服务器的根目录提供一些文件,包括:
/manifest.json
/sitemap.xml
/favicon.ico
/robots.txt
/browserconfig.xml
/site.webmanifest
虽然可以使用元标记设置大多数这些路径,但旧版浏览器会忽略它们,如果未提供这些确切的文件名则会出错。
在撰写本文时,NextJS中有ongoing work for supporting offline。但还没有准备好。
如果您不需要支持旧版浏览器并且您不需要高级搜索引擎优化,则可以使用NextJS的Head
组件(see documentation)来定义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)提供,因此如果您需要定义此文件,此解决方案不适合。
正确的解决方案是从您的快速服务器提供这些文件
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}`)
})
})
注意:此代码直接来自the NextJS examples repository