introduction

默认来说,Next.js 通过next start启动自己的服务器,如果你有存在的后端服务,你仍然通过Next.js 使用它(但这并不是自定义服务器), 一个自定义的Next.js 服务器允许你百分百编程式启动为了使用自定义的服务器模式 .. 大多数这个时候,你完全不需要,除非你需要完全自定义 …

注意: 一个自定义服务器不能够在Vercel上进行部署 …

在决定使用自定义服务器之前,请保持它应该仅仅能够被用于(Next.js 集成的路由已经不能满足应用需求),一个自定义服务器将丢失掉重要的性能优化,例如无服务器函数以及 自动静态优化 ….

让我们来查看一下一个自定义服务器的示例:

  1. // server.js
  2. const { createServer } = require('http')
  3. const { parse } = require('url')
  4. const next = require('next')
  5. const dev = process.env.NODE_ENV !== 'production'
  6. const app = next({ dev })
  7. const handle = app.getRequestHandler()
  8. app.prepare().then(() => {
  9. createServer((req, res) => {
  10. // Be sure to pass `true` as the second argument to `url.parse`.
  11. // This tells it to parse the query portion of the URL.
  12. const parsedUrl = parse(req.url, true)
  13. const { pathname, query } = parsedUrl
  14. if (pathname === '/a') {
  15. app.render(req, res, '/a', query)
  16. } else if (pathname === '/b') {
  17. app.render(req, res, '/b', query)
  18. } else {
  19. handle(req, res, parsedUrl)
  20. }
  21. }).listen(3000, (err) => {
  22. if (err) throw err
  23. console.log('> Ready on http://localhost:3000')
  24. })
  25. })

server.js并没有通过babel 或者 webpack,确保语法以及来源是兼容于当前运行的node版本 …

为了运行自定义服务器(你需要更新 package.jsonscripts部分)

  1. "scripts": {
  2. "dev": "node server.js",
  3. "build": "next build",
  4. "start": "NODE_ENV=production node server.js"
  5. }

自定义服务器使用以下导入关联Next.js 应用的服务器 ..

  1. const next = require('next')
  2. const app = next({})

上面的next导入是一个函数(能够接收以下选择的对象)

  • dev: Boolean 是否在开发模式中启动Next.js,默认为false
  • dir: StringNext.js 项目的位置(默认当前项目)
  • quiet: Boolean是否隐藏错误信息包括服务器信息 默认为false
  • conf: object 这个对象能够使用在next.config.js中,默认为false …
  • 返回的app能够被用来让Next.js 处理请求 …

禁用文件系统路由

默认来说,Next将为pages中每一个文件根据路径名 匹配文件名提供路由,如果你的项目使用了自定义服务器,这些行为可能导致从多个路径下提供相同内容,这可能导致SEO 以及UX 的问题 …

为了禁用这个行为并且阻止基于pages的文件路由,修改next.config.js并禁用useFileSystemPublicRoutes配置 …

  1. module.exports = {
  2. useFileSystemPublicRoutes: false
  3. }

注意到这个属性禁用了来自SSR 的文件名路由,客户端路由仍然能够访问这些路径,当使用这个选项的时候,应该保证编程式导航到不需要的路由 ..

你也许希望配置客户端路由去禁用客户端重定向到文件名路由(对此参考router.beforePopState https://www.nextjs.cn/docs/api-reference/next/router#routerbeforepopstate)