微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否可以不重建整个应用程序而仅在 Nextjs 中生成新的静态文件?

如何解决是否可以不重建整个应用程序而仅在 Nextjs 中生成新的静态文件?

我刚刚开始使用 NextJs getStaticProps,在 build time 生成静态文件整洁。但我的内容不会保持不变,我需要更新静态文件,但每次修改时重建应用程序的成本很高。有没有办法只生成新的静态文件getServerSideProps 原来花费了大量时间直到第一个字节。

解决方法

如果我理解正确,您正在寻找增量静态再生

要启用它,您需要在 revalidate 中添加 getStaticProps 时间。当您的内容发生更改并达到重新验证时间后,将生成一个新的静态页面并由服务器提供服务。根据您的内容更改频率,您可以相应地更改重新验证时间。

export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,},// Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every 10 seconds
    revalidate: 10,// In seconds
  }
}

参考

https://nextjs.org/docs/basic-features/data-fetching#incremental-static-regeneration

,

根据您的内容类型 Incremental Statatic Regeneration 可能是一个很好的解决方案。但根据我的经验,它在呈现目录/类别页面时引入了其他问题。由于 nextjs 不知道您的数据的一部分是否依赖于其他数据,因此它可能会呈现旧的目录页面,其中包含指向不再存在的帖子或产品的链接。这通常与动态路由的“回退”功能结合使用。

它也不会在您进行更改后立即刷新您的页面,因此您只能在一段时间后看到结果。

可能的解决方法是通过 ajax 动态加载类别页面上的帖子/产品。您将失去一部分 UX 和 SEO,但另一方面,此解决方案相对易于维护。

还有一个选项,或者更确切地说,通过直接访问自定义服务器中的缓存来重建部分保存的内容。将“purge=1”添加到您要刷新的页面地址。

const { ServerResponse,createServer } = require('http')
const next = require('next')
const { promises } = require('fs')
const path = require('path')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

const purgeByPath = async url => {
  const pathname = url == '/' ? '/index' : url
  const fullPathname = `.next/server/pages${pathname}`
  const fullPathHTML = `${fullPathname}.html`
  const fullPathJSON = `${fullPathname}.json`

  try {
    await promises.unlink(fullPathHTML)
    await promises.unlink(fullPathJSON)
  } catch (err) {
    console.log(`Could not unlink cache files: ${err}`)
  }

  await app.incrementalCache.cache.del(pathname)

  let req = new Request(process.env.BASE_HOST + url)
  let res = new ServerResponse(req)

  await app.renderToHTML(req,res,url,{ _nextDataReq: true })
}

app.prepare().then(() => {
  createServer(async (req,res) => {
    const url = new URL(req.url,"http://localhost:3000/")

    if (req.method == 'POST' && req.url == '/purge-cache') {
      let raw = ''
      req.on('data',chunk => raw += chunk)
      req.on('end',async () => {
        const data = JSON.parse(raw)

        if (!data || !data.urls) {
          res.statusCode = 400
          res.end()
          return
        }

        for (let url of data.urls) {
          console.log(`Cleaning cache on: ${url}`)
          await purgeByPath(url)
        }

        res.end()
      })
    } else if (url.searchParams.get('purge') == '1') {
      await purgeByPath(req.url)
      res.end()
    } else {
      handle(req,res)
    }
  }).listen(3000,(err) => {
    if (err) throw err
    console.log(`> Ready on http://localhost:3000/`)
  })
})

静态缓存由两部分组成:

  • 位于 .next/server/pages 的静态缓存文件,其中每个路由可能有两个文件 html 和 json。您很可能需要同时删除两者。
  • 内存缓存。一旦您的应用程序缓存了一个页面并将其保存到内存中,它就不会转到硬盘驱动器上的文件,而是从内存中加载内容。所以你也需要删除它。

未记录缓存实现,可能会在未来版本中交换或删除。

这不适用于 vercel,并且在缩放方面存在一些问题。您还应该添加某种安全令牌来清除路由。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。