自定义服务端路由

Examples

一般你使用next start命令来启动 next 服务,你还可以编写代码来自定义路由,如使用路由正则等。

当使用自定义服务文件,如下面例子所示叫 server.js 时,确保你更新了 package.json 中的脚本。

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

下面这个例子使 /a 路由解析为./pages/b,以及/b 路由解析为./pages/a;

  1. // This file doesn't go through babel or webpack transformation.
  2. // Make sure the syntax and sources this file requires are compatible with the current node version you are running
  3. // See https://github.com/zeit/next.js/issues/1245 for discussions on Universal Webpack or universal Babel
  4. const { createServer } = require('http')
  5. const { parse } = require('url')
  6. const next = require('next')
  7.  
  8. const dev = process.env.NODE_ENV !== 'production'
  9. const app = next({ dev })
  10. const handle = app.getRequestHandler()
  11.  
  12. app.prepare().then(() => {
  13. createServer((req, res) => {
  14. // Be sure to pass `true` as the second argument to `url.parse`.
  15. // This tells it to parse the query portion of the URL.
  16. const parsedUrl = parse(req.url, true)
  17. const { pathname, query } = parsedUrl
  18.  
  19. if (pathname === '/a') {
  20. app.render(req, res, '/b', query)
  21. } else if (pathname === '/b') {
  22. app.render(req, res, '/a', query)
  23. } else {
  24. handle(req, res, parsedUrl)
  25. }
  26. }).listen(3000, err => {
  27. if (err) throw err
  28. console.log('> Ready on http://localhost:3000')
  29. })
  30. })

next的 API 如下所示

  • next(opts: object)
    opts 的属性如下:

  • dev (boolean) 判断 Next.js 应用是否在开发环境 - 默认false

  • dir (string) Next 项目路径 - 默认'.'
  • quiet (boolean) 是否隐藏包含服务端消息在内的错误信息 - 默认false
  • conf (object) 与next.config.js的对象相同 - 默认{}
    生产环境的话,可以更改 package.json 里的start脚本为NODE_ENV=production node server.js

禁止文件路由

默认情况,Next将会把/pages下的所有文件匹配路由(如/pages/some-file.js 渲染为 site.com/some-file

如果你的项目使用自定义路由,那么有可能不同的路由会得到相同的内容,可以优化 SEO 和用户体验。

禁止路由链接到/pages下的文件,只需设置next.config.js文件如下所示:

  1. // next.config.js
  2. module.exports = {
  3. useFileSystemPublicRoutes: false
  4. }

注意useFileSystemPublicRoutes只禁止服务端的文件路由;但是客户端的还是禁止不了。

你如果想配置客户端路由不能跳转文件路由,可以参考Intercepting popstate

动态前缀

有时你需要设置动态前缀,可以在请求时设置assetPrefix改变前缀。

使用方法如下:

  1. const next = require('next')
  2. const micro = require('micro')
  3.  
  4. const dev = process.env.NODE_ENV !== 'production'
  5. const app = next({ dev })
  6. const handleNextRequests = app.getRequestHandler()
  7.  
  8. app.prepare().then(() => {
  9. const server = micro((req, res) => {
  10. // Add assetPrefix support based on the hostname
  11. if (req.headers.host === 'my-app.com') {
  12. app.setAssetPrefix('http://cdn.com/myapp')
  13. } else {
  14. app.setAssetPrefix('')
  15. }
  16.  
  17. handleNextRequests(req, res)
  18. })
  19.  
  20. server.listen(port, (err) => {
  21. if (err) {
  22. throw err
  23. }
  24.  
  25. console.log(`> Ready on http://localhost:${port}`)
  26. })
  27. })