NextJS:如何在根处理多个动态路由
Posted
技术标签:
【中文标题】NextJS:如何在根处理多个动态路由【英文标题】:NextJS: How to handle multiple dynamic routes at the root 【发布时间】:2020-05-04 13:13:48 【问题描述】:目标:我想实现 github 风格的路由,其中
github.com/abcd
中的abcd
可以解析为用户个人资料页面或团队页面。
我目前有一个可以工作的版本(见下文)。不幸的是,在 2 条动态路线之间导航时,我偶尔会出现白页闪烁。
我的服务器文件如下所示:
const express = require('express');
const next = require('next');
const parse = require('url');
const resolveRoute = require('./resolveRoute');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const nextApp = next(
dev,
);
const nextHandle = nextApp.getRequestHandler();
const STATIC_ROUTES = [
'/about',
'/news',
'/static',
];
const DYNAMIC_ROUTE_MAP =
user: '/[user]',
team: '/teams/[team]',
;
nextApp.prepare().then(() =>
const server = express();
server.get('*', async (req, res) =>
// pass through next routes
if (req.url.indexOf('/_next') === 0)
return nextHandle(req, res);
// pass through static routes
if (
req.url === '/' ||
STATIC_ROUTES.map(route => req.url.indexOf(route) === 0).reduce(
(prev, curr) => prev || curr,
)
)
return nextHandle(req, res);
// try to resolve the route
// if successful resolves to an object:
// type: 'user' | 'team'
const resolvedRoute = await resolveRoute(req.url);
if (!resolvedRoute || !resolvedRoute.type)
console.error('???? Unable to resolve route...');
return nextHandle(req, res);
// set query
const pathname = parse(req.url);
const paths = pathname.split('/').filter(path => path.length > 0);
const query =
[resolvedRoute.type]: paths.length > 0 ? paths[0] : null,
;
// render route
return nextApp.render(
req,
res,
DYNAMIC_ROUTE_MAP[resolvedRoute.type],
query,
);
);
server.listen(port, err =>
if (err) throw err;
console.log(`???? Ready on http://localhost:$port`);
);
);
我想知道是否有更好的方法来处理这个问题,或者我是否需要离开 NextJS。
【问题讨论】:
【参考方案1】:关于使用 s-s-r 和 SSG 页面的一个补充内容,您需要通过在 URL 中添加“-s-s-r”前缀来区分具有动态 URL 的页面。
例如,你需要一些页面是 s-s-r,那么你可以在 pages 下创建一个 s-s-r 文件夹,你可以在其中放置页面 [[...path ]].js 与 getServerSideProps。然后你可以在 async rewrites() :
下的 next.config.js 中使用这样的重写
source: '/:path*/:key-s-s-r', destination: '/s-s-r/:path*/:key-s-s-r'
涵盖此类 URL:
/page-s-s-r /zh/page1/page-s-s-r /zh/page1/page2/page-s-s-r /zh/page1/page2/page3/page-s-s-r等等
【讨论】:
【参考方案2】:Next.JS 内置了动态路由,不需要您创建自定义 server.js 文件。如果你想与 Next.JS 完全兼容,你应该改用它的动态路由。
要在 Next.JS 中创建动态路由,您可以创建名称用方括号括起来的页面,例如/pages/[username].js
。这将匹配您的基本域上的所有路由,因此您可以使用 github 设置您提到的示例,例如http://yourwebsite.com/csbarnes 和 http://yourwebsite.com/anotherusername。
在上面的示例中,您可以从 getInitialProps
的查询参数中获取 Next.JS 页面中的用户名,就像使用任何查询字符串参数一样:
static getInitialProps(query)
console.log(query.username); // the param name is the part in [] in your filename
return query; // you can now access this as this.props.query in your page
Next.JS 总是在动态路由之前匹配静态路由,这意味着您的 /pages/
目录可能如下所示:
pages/index.js -> (will match http://yourwebsite.com)
pages/about.js -> (will match http://yourwebsite.com/about)
pages/contact.js -> (will match http://yourwebsite.com/contact)
pages/[username].js -> (will match http://yourwebsite.com/[anything_else])
多段
您可以有多个分段动态路由,例如使用pages
目录中的文件夹的http://website.com/[username]/[repo]
:
pages/[username].js -> (matches http://yourwebsite.com/[username])
pages/[username]/[repo] -> (matches http://yourwebsite.com/[username]/[repo])
在这种情况下,您的查询对象将包含 2 个参数: username: ..., repo: ...
。
路由“前缀”
如果您愿意,可以通过在 pages
目录中创建文件夹来拥有多个具有不同“前缀”的动态路由。下面是一个带有website.com/[username]
路由和website.com/teams/[team]
路由的示例文件夹结构:
不同段的动态数量
您还可以拥有包含任意数量的动态分段的动态路由。为此,您需要在动态路由文件名中使用省略号(“...”):
/pages/[...userDetails].js -> (will match http://website.com/[username]/[repo]/[etc]/[etc]/[forever])
在这种情况下,您的 this.props.userDetails
变量将返回一个数组而不是字符串。
【讨论】:
对,问题是我想要两条动态路由,/pages/[username].js
和 /pages/[team].js
,这不起作用(可以理解)。
在你的问题中,你的“团队”路线是http://website.com/teams/[teamname]
,所以你可以在 NextJS 中做到这一点没问题。只需在您的页面目录中放置一个名为teams
的文件夹,这样您就有了/pages/[username].js
和pages/teams/[team].js
。这应该工作:)
我刚刚测试过它可以工作。这是我的文件夹结构:i.imgur.com/H9PfW29.jpg
啊,那么您需要在页面代码中处理它。 IE。抓取字符串,确定是团队还是用户,然后导入正确的组件以显示正确的页面。
真正的答案:这是一个设计糟糕的路由方案,并且随着站点的扩展,将动态路由作为根将引发各种令人头疼的问题。为动态路由制作适当的前缀路由 - 在这种情况下,/pages/users/[username].js
和 /pages/teams/[team].js
会使事情变得更简单。我非常怀疑是否有这样的用户路由要求处于根级别。以上是关于NextJS:如何在根处理多个动态路由的主要内容,如果未能解决你的问题,请参考以下文章
Nextjs 中使用 getServerSideProps 进行动态路由
Amazon CloudFront 中的 NextJS 动态路由
在 NextJS 中使用“getStaticPaths”和“getStaticProps”创建动态路由