如何使用 Next.js 检查自定义服务器中是不是存在页面

Posted

技术标签:

【中文标题】如何使用 Next.js 检查自定义服务器中是不是存在页面【英文标题】:How to check if a page exist in a custom server using Next.js如何使用 Next.js 检查自定义服务器中是否存在页面 【发布时间】:2020-05-02 03:15:21 【问题描述】:

next@9.1.7 与带有 express 的自定义服务器一起使用。在handle(req, res) 调用之前,如何在我的server.js 中知道 next.js 页面是否存在?

我尝试使用 app.router.execute,但它总是返回 false。所以我想这不是办法。我检查了 Next.js 文档,但没有得到任何解决方案……有人有想法吗?

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

// ...

server.get('*', async (req, res) => 
  const  url, fixed  = fixUrl(req)

  // pageExists is always false ????...
  const pageExists = await app.router.execute(req, res, req.url) 

  // Fix the url and redirect only if the page exists 
  // (to avoid redirects to 404 pages)
  if (fixed && pageExists) 
    res.redirect(301, url)
    return
  

  handle(req, res)
)

【问题讨论】:

我知道这不是一个优雅的解决方案,但是检查 response.statusCode 怎么样?基本上你对当前路线发出请求并检查状态码。 我尝试了res.end 事件。但是看起来在状态 200 之后使用 301 重定向会出错:Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client 我的意思是像这样var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl; fetch(fullUrl).then((res) => status = res.status; console.log( res.status ) ).catch((err) => // handle error for example console.error(err); ); 还要注意,这个检查不应该在server.get('*' 内部进行,因为它会检查所有请求(css,imgs,ecc ...)而不是你应该仅在路线内部进行此检查。 【参考方案1】:

我终于解决了:

const glob = require('glob')
const path = require('path')

// ...
const pagesDir = path.resolve(`$__dirname/../src/pages`)
const pages = glob.sync(`$pagesDir/**/*.js`)
  .map(p => p
    .replace(pagesDir, '')
    .replace('index.js', '')
    .replace('.js', '')
  )

// ...

server.get('*',(req, res) => 
  const  url, fixed  = fixUrl(req)

  if (fixed && pages.includes(url.split('?')[0])) 
    res.redirect(301, url)
    return
  

  handle(req, res)
)

如果有人知道更优雅的解决方案,将受到欢迎。

【讨论】:

目前这不是最好的解决方案,因为它不适用于动态路由【参考方案2】:

这个可怕的 hack 并没有在调用 handle 之前严格告诉您路由是否存在,但它确实让您在下次向 res 呈现任何内容之前挂钩并应用您自己的 404 错误自定义处理。

const errorRenderer = app.server.renderErrorTohtml;
app.server.renderErrorToHTML = function(err, req, res, pathname, query) 
    if (res.statusCode == 404) 
        // handle the 404 however you like
        return null;
     else 
        return errorRenderer.apply(this, arguments);
    
;

【讨论】:

以上是关于如何使用 Next.js 检查自定义服务器中是不是存在页面的主要内容,如果未能解决你的问题,请参考以下文章

使用 Express 服务器将多个参数传递给 Next.js 自定义 URL

如何在 Next.js 中使用自定义主题配置 Ant Design 并支持 CSS 模块功能

自定义箭头 Swiper Slider + Next.js + Sass

如何在 Next.js 中添加自定义图像占位符?

如何使用 next.js 获取客户端 cookie?

自定义 Next.js - getRequestHandler 和渲染函数之间的区别