Next.js: 与React Router 4一起使用

创建于 2017-04-05  ·  122评论  ·  资料来源: vercel/next.js

是否可以将next.js与新的React Router V4一起使用?

最有用的评论

@timneutkens添加

所有122条评论

@Knaackee您是否尝试过这种可能性? 我也想知道是否有人将其与任何版本的RR一起使用?

接下来有自己的路由器,为什么要使用RR?

当我将现有应用程序移植到Next时, @ sergiodxa称重选项。 我有一个静态的嵌套路由配置,正在工作,想知道我可以继续使用什么,什么不可以。

@ oyeanuj🤔您可以逐渐迁移到Next,只需将Next.js设置为处理1条路由,并使用代理将当前应用程序和Next.js都拥有,然后将第二条路由从RR移至Next.js,您可以在迁移时保留当前应用程序的方式,最终您将在Next.js中拥有所有功能

从示例看,next具有单个路由表,例如RRv2-3,并且不支持RRv4等“嵌套路由”。 这些很好。

我会尝试使用RR还是我不知道的重大警告?

@igl您是否找到解决方案?

嵌套路由的新的react-router 4范例改变了游戏规则,并且是我们当前项目中必须具备的功能。 我想知道是否有人成功将rr4与next.js配合使用?

MemoryRouter确实可以工作,如果不符合预期的话...
否则,动态组件只能是客户端,其中HashRouter可以正常工作...

const AdminPage = dynamic(
  import('..../AdminPage'),
  { ssr: false }
);

我也遵循@malixsys方法,并使用react-router处理客户端路由,并使用next路由器处理所有服务器呈现的内容。

@malixsys @pegiadise您能否详细说明如何同时使用下一个路由器和react-router?

您可以在componentDidMount设置一个标志,并在标志为真时有条件地渲染<Router /> 。 ( componentDidMount不在服务器run上运行)

实际上,我们即将将React Router集成到Next.js中:)
https://twitter.com/rauchg/status/948318111828099072

这还在发生吗? 我可以看到V6金丝雀的发行说明,但没有提及。

最终。 绝对在我们的脑海中。 目前,我们还有其他优先事项(布局组件,可靠的开发以及其他一些长期存在的未解决问题)。

真可惜,这对于团队来说可能不是很重要,但基本上这是阻止像我这样的人开始使用它的唯一方法。 我仔细阅读了您的教程,直到说到必须设置两次路由然后放弃为止。

@timneutkens添加

真可惜,这对于团队来说可能不是很重要,但基本上这是阻止像我这样的人开始使用它的唯一方法。

相同。

我们至少可以重新打开此问题以便对其进行跟踪吗?

我将重新打开它,但是请注意,这是一个开源项目,由于我们将Next.js用于所有内容,因此对于zeit.co,目前我们还没有很好的理由。

这就是为什么我说这是长期目标的一部分,不能立即实现,但我们正在朝着这一目标努力。

我在Next 6中引入的功能实际上正在努力支持React Router。

对于Next 6,我们还有其他优先事项,它们正在极大地提高Next.js的可靠性和可伸缩性,例如将页面解析速度提高100倍,App Component,使下一个导出工作在开发中,babel 7等。

我希望这能阐明我先前的评论。

因此,TLDR为:

  • 我们将要这样做,但不会立即
  • Next 6对Next.js的不同部分进行了许多改进

为了进一步扩展@timneutkens的评论:我们当然想要RR,但是在当前Router中没有任何紧迫的限制使其成为优先事项。 您可以想象的所有路由用例都已使用当前的Next.js API成功实现

我们确实需要React Router支持的原因有两个:

  • 简化我们自己的Next.js代码库,而无需维护我们自己的路由器,使事情变得更小且模块化
  • 简化已经使用RR的大型应用程序的迁移路径

因此,我同意我们应该保持这个问题公开!

与此相对的是,没有react-router意味着下一个可以很好地与现代继电器一起使用,这也是我们从旧的react-router应用切换到next的原因之一。

@merry去年我是否在使用继电器现代的RRv4应用程序。 关心更具体吗?
我不记得我们因为任何一个而遇到严重问题。

@igl这是根据中继的文档: https: //facebook.github.io/relay/docs/en/routing.html#react -router-https-reacttrainingcom-react-router

问题在于RRv4的组件方法不允许在预编译步骤中进行确定性操作,这可能会导致客户端出现请求瀑布。

@rauchg出于兴趣,我对Next的路由器的理解是它不支持嵌套路由的概念,因此您可以在页面内导航时保留外部标记。 您知道目前的路由器是否有办法使之成为可能吗?

@dbbk检查我们的nextgram示例应用程序(https://github.com/now-examples/nextgram),它确实做到了

在下一个5中,我们将通过使所有页面都扩展的顶级布局组件来完成“外部标记”:基础布局具有顶级导航,然后是一些子布局,这些扩展为列表/详细信息/等扩展了基础,然后我们的页面组件使用自己的特定内容扩展了这些子布局。 在接下来的6中,您还可以使用_app.js来完成基本的“外部标记”。

下一个版本是否可以配置为选择非React Router的路由解决方案?

嗨,我只需要React Router即可将道具传递到页面(使用<Route render ={} />而不是<Route component ={} /> ),我可以使用Next吗?

从示例看,next具有单个路由表,例如RRv2-3,并且不支持RRv4等“嵌套路由”。 这些很好。

你好

这是否意味着我必须为一条路线创建一个页面?

假设我有2条路线sign uplog in 。 我会有1个页面共享相同的布局,唯一的区别是表格的面积。 那就是我只需要在pages文件夹中创建1个文件。 但是在接下来的路线中,我必须在pages文件夹中创建2个文件。 是吗?

如果是这样,那么布局会随每个导航(而不只是表单区域)重新安装,对吗?

@ 7c78您可以做的一件事是利用_app.js来持久化所有页面的页面布局。 另一件事是创建共享的布局组件,您可以在各个页面上重复使用这些组件,以实现所需的功能:

// pages/login.js

class LoginPage extends React.Component {
  render() {
    return (
      <AuthForm>    // same component can be reused in signup
        <form>
          ...implementation of login
        </form>
      </AuthForm>
    );
  }
}

另外,您可以执行我们最近做的事情,并定义页面组件都可以扩展的基本布局组件:

//layouts/baseAuth.js

class BaseAuth extends React.Component {
  abstract formContent();  // we use typescript, but you can have the same concepts
  abstract formSubmit():

  render() {
    return (
      <SomeStyledDiv>
        <form>
          {this.formContent()}
          {this.formSubmit()}
        </form>
      </SomeStyledDiv>
    );
  }
}

然后,您只需在登录和注册页面中扩展BaseAuth并在每个页面中定义formContentformSubmit (这些是玩具示例,因为我不知道您的确切要求)。

@merrywhether
我目前使用您的方法,下面的示例也使用它。

但我担心的是,我需要为单独的表单创建单独的页面。 那是布局被重用,但页面不被重用。 并在每次导航时重新安装布局。

使用RRv4,我们只有一个页面,并且表单是根据路线(而不是整个页面)呈现/重新安装的。 路线只是组成部分。

感谢您的快速回复!

@ 7c78关于重新安装,这是正确的,尽管我确实认为当vDOM解析为相同状态时,DOM节点已被重新使用。

这不是我们一直在担心的事情,因为我们也不能将React-Router与Relay-Modern一起使用,因此无论如何我们都必须使用此模式。

@merry我是否对vDOM不确定,因为服务器会为每个路由返回新的document / html。 抱歉,忽略这个假设,我只是一个新手。

我同意我们仍然必须使用此模式。 谢谢!

您可以通过将整个应用程序放在pages / index.js中来将RR与next.js结合使用,但是您失去了next的一些好处,例如开箱即用的代码拆分功能,必须自己进行设置。

如果考虑到Reach Router,我会很喜欢。 它与react-router非常相似,并带来一些重要的好处:

  • 它解决了有关链接生成和焦点管理(https://reach.tech/router/accessibility)的一些重要问题。
  • 它重量更轻(在撰写本文时)

到达路由器也很棒

RR样式的动态路由是一个不错的API,但是静态(可静态分析)路由也带来了很多好处。 两种方法都不是灌篮高手。

@sorokinvj目前仅通过插件支持.. https://github.com/fridays/next-routes

静态链接非常基础,甚至不支持链接中的参数...

我现在正在使用第三方程序包next-routes https://github.com/fridays/next-routes绕过它

从我的iPhone发送

2018年10月24日,23:01,Andy Ingram [email protected]写道:

RR样式的动态路由是一个不错的API,但是静态(可静态分析)路由也带来了很多好处。 两种方法都不是灌篮高手。

-
您收到此消息是因为您已订阅此线程。
直接回复此电子邮件,在GitHub上查看,或使该线程静音。

我们暂时还使用next-routes ,但我相信下一个团队正在通过正则表达式文件名(受Sapper启发)在其文件系统路由中添加路径参数。

@merry我是否next-routes ,但希望它是Next.js核心的一部分。

你提到

我相信下一小组正在努力添加路径参数...

我很好奇,您对此有什么参考吗? 也许路线参数尚待解决? 我找不到一个...也许插件可以解决需求,这将是今后的推荐解决方案。

@curran来源是来自sapper.js开发人员的一条推文,他说下一步是从sapper.js汲取灵感,并在将来的版本中实现regex-filename-routing。 当然,Twitter是什么,我一生都找不到原始的推文。

发行于2017年4月5日,现在是2019年2月27日。将近2年,并且没有解决方案
也许是时候用一些好的东西来代替内置式路由器了吗?

哎哟。 这对那些将大量时间投入到路由解决方案中的NextJS开发人员是一种侮辱。

我一开始想念ReactRouter。 现在,我什至不记得在有人提醒我之前,NextJS具有不同的路由器。 例如,详细的Link API很容易与代理一起包装(取决于您的数据/ API体系结构)。 分享这个最高机密:😆

import _Link from "next/link"
export function Link({as, children, href}) {
  as = as || QS.parse(U.parse(href).query || "").url || null // QS, U are parsing libs
  return <_Link as={as} href={href}>
    {children}
  </_Link>
}
<Link as="/about" href="/page?url=/about"/> verbose
→
<Link href="/page?url=/about"/> ok

我认为我们所有人应该花更少的时间抱怨第二件事

@ ivan-kleshnin尼斯,我添加了一个类似的包装器

根据先前的评论,我想指出https://www.contributor-covenant.org/version/1/4/code-of-conduct

我已经隐藏了说的评论。

对于大多数用例,我对next/router没问题。
但是它应该在universal routing部分上有所改善。
在Now 2部署的情况下,我很乐意只接受now.json并将其用于在我的应用程序中进行路由。

如果要在nextJs项目中实现RR4,则需要做两件事:

  1. 防止使用NextJS SSR,通过使用next/dynamic可以做到。
  2. 如果用户重新加载页面,则使用HashRouter代替BrowserRouter ->如果用户重新加载页面,浏览器可以加载前一页(而不是404页)

如果要在nextJs项目中实现RR4,则需要做两件事:

  1. 防止使用NextJS SSR,通过使用next/dynamic可以做到。
  2. 如果用户重新加载页面,则使用HashRouter代替BrowserRouter ->如果用户重新加载页面,浏览器可以加载前一页(而不是404页)

感谢您的回复,对我帮助很大。

@ reach / router和react-router 5正在合并: https :

这如何影响next.js?

@ alp82由于Next.js仍然不使用React Router或Reach Router,因此它完全不会影响Next.js。

我需要在nextjs中使用切换路由功能来在索引页面中呈现多个页面组件。
所以我该如何在nextjs中实现呢?

如果要在nextJs项目中实现RR4,则需要做两件事:

  1. 防止使用NextJS SSR,通过使用next/dynamic可以做到。
  2. 如果用户重新加载页面,则使用HashRouter代替BrowserRouter ->如果用户重新加载页面,浏览器可以加载前一页(而不是404页)

如果您要重新呈现上一页而不会引发404错误,那么只需在快递服务器文件中使用此获取路线即可。

server.get('your params',(req,res)=> {
const actualPage ='/ your_page'
const queryParams = {id:req.params.id}
app.render(req,res,actualPage,queryParams)
})

我记录了一种将next.jsreact-router next.js结合使用的方法,该方法提供单个入口点文件,而不是基于本机文件系统的路由,并完全保留本机SSR功能。

我很乐意收到反馈并改善自己的工作。

该文档可作为:

干杯!

当您最终以单个入口点结束时,我将极力劝阻您不要这样使用react-router,这意味着(大量)开发速度会变慢,将过多代码交付给客户端的机会更大,并且对自动静态导出等优化的可见性也会降低。

@timneutkens也许我错了。 但是对于延迟加载,路由配置只是一个配置文件。 我认为这里不会影响可扩展性或性能。 我想了解更多。
react-router的好处是开发人员可以完全控制代码。

@timneutkens ,我不会在这里开始争论,但请您取消隐藏我的评论。 我花了一些时间将自己的工作提供给社区,并且回过头来,我看不出人们如何沉默可以帮助开源开发。

对于您提到的要点, @ timneutkens是一个权衡的问题。 我的是一个实验,用于说明如何将Next.js与其他设置一起使用。

客户端上的代码过多

任何现代捆绑包都可以将客户端资产拆分为多个块,而react-router路由实际上是非常方便的拆分点。

开发时间更长

对于大型项目来说,这是一个代价,但是如果对Webpack进行一些适当的微调,那么这是无法解决的。

没有静态出口

我同意静态导出是重要的优化层。 通常,Next.js应用程序服务的大多数页面无论如何都必须检索动态数据,并且不能从静态导出中受益。

对此问题不乏解决方案。 例如。 仍然可以手动声明要静态导出的路由列表

我隐藏评论的原因是,这是一个高流量问题,并且不反映我们建议构建Next.js应用程序的建议。 如果有人最终想使用react-router,那么他们最终将以您的示例为盲目,而不是研究如何使用Next.js正确设置路由。

对于大型项目来说,这是一个代价,但是如果对Webpack进行一些适当的微调,那么这是无法解决的。

您无法根据自己的方法加快开发时间的启动,没有对webpack配置进行特定的微调,因为webpack只会编译并监视您导入的每条路由,从而大大降低了对通用组件的编辑速度。 因此,为什么Next.js具有按需输入: https ://nextjs.org/blog/next-8#improved -on-demand-entries

此外,还有(自动)路由预取等。我可以在此处输入大量的细节,但是tldr的问题是,您最终会获得较差的开发人员体验和应用程序。

我不介意取消隐藏该注释,如果它正确地反映出您唯一想使用它的地方就是迁移已经使用react-router的应用程序,然后逐渐移至多个页面。

嘿@timneutkens
您是否可以列举一些可以静态分析的专家,而动态路由解决方案是不可能的?

像这样的东西https://github.com/jaredpalmer/after.js吗?

我已经阅读了所有注释,但仍不清楚在next.js的将来迭代中是否将包含RR4 +或将其可选。 是路由器路线图还是类似的东西?

@laurencefass似乎没有计划支持react-router (截至今天)。

对我而言,Next.js的路由系统已经足够成熟,因此我们可能仍然不需要它了:)

“对我而言,Next.js的路由系统已经足够成熟,因此我们可能不再需要它了:)”

除了那些寻求在现有代码库中逐步采用Next.js的用户之外。 我认为更有用的讨论可能不是“ Next.js路由与react-router路由”。 我认为更有用的讨论是“如何使用React-Router逐步将大型应用程序迁移到Next.js?”

不过,Next的路由器没有嵌套路由视图的能力,对吗? 到路线的每次导航都会破坏DOM并刷新它。 嵌套视图是很常见的要求。

@dbbk我听说nextjs团队正在努力。

next js对于路由器非常灵活。 https://dev.to/toomuchdesign/next-js-react-router-2kl8

我正在将网站从普通的JS和jQuery代码迁移到React。 与旧代码不同,我需要防止在更改页面时停止播放音乐,因此我使用了React Router。

现在出于SEO的目的,因为我从Google搜索获得了一些良好的访问量,所以我需要保持这一点。 因此,我希望将Next.js与SSR结合使用以获得更好的性能。

如果Next.js能够在服务器端呈现页面,然后在客户端加载页面,则Next.js会在React Router的控制下进行导航,这样,如果用户正在听音乐,则Next.js链接将不会不必离开当前页面即可停止播放音乐?

O.Next.js可以仅进行客户端路由吗?

如果集成React Router将能够解决此问题,那么我就来了。因为一旦应用程序到达客户端,连续播放音乐对我来说是必须的。

next js对于路由器非常灵活。 https://dev.to/toomuchdesign/next-js-react-router-2kl8

@laurencefass ,这是一个非常好的方法,我之前读过它。 文章说,Next.js团队不推荐它,也不知道为什么。 但是对我来说似乎很好

@KeitelDOG不需要使用react-router,Next.js路由将为您带来相同的好处,而且由于自动代码拆分,您的应用程序也更轻巧(使用react-router不会很容易)

_edit:我要补充一点:也许react-router的唯一优点是同一视图功能中的简单嵌套路由,Next.js路由器应该可以解决95%的用例_

@martpie感谢您的答复,这就是我昨晚在Link组件中看到的内容。 然后,Next.js是我想要的混合服务器-客户端。

对于动态地控制其嵌套路由的组件,我真的很喜欢React Router。 但是我非常确定我可以解决这个问题,因为我不是将React网站更改为Next.js,而是计划和测试将JS-jQuery网站更改为React多页应用程序,而不会失去我的SEO优势在Google上。 所以我认为我应该使用Next.js

@timneutkens有什么计划在Next.js 10中支持它吗?

@TrejGun谢谢,这绝对不是话题。

有什么计划吗?
next/router很棒,它提供了很多帮助。 但是我们需要更专业的路由器来应对复杂的应用。 React-router是路由器的领导者。
也许可以参考after.js

是的,基于页面的系统根本不够复杂,无法处理可能受益于嵌套路由的复杂数据驱动的应用程序。

React-router即将发布v6版本,这将是迄今为止最好的路由器。 我期待next.js支持它。

更好的方法是将next.jsrouter分开,使人们可以自由选择自己喜欢的router

+1为先前的评论。 next.js令人惊讶,我不使用它的唯一原因是Router缺乏灵活性。 请在将来的版本中支持React Router 6或使路由器可互换。

真正热衷于React Router的人们可能对跟随新项目“ Remix”感兴趣,这是由同一创作者使用React Router的Ne​​xt.js替代品:

我认为问题是由于SSR,服务器端道具等原因,该框架与该路由器紧密相连。

Next是在考虑性能的基础上构建的,服务器端react-router具有主要的性能含义,即在知道要尝试呈现的内容以及所需的数据之前,必须遍历DOM树。 getInitialProps的全部目的是使您不必在获取数据之前进行一次性的反应渲染,这是许多框架在服务器上(以及在客户端中,表现为请求瀑布)。 接下来,可以通过使每个顶级页面声明所有子组件可能需要的各种数据模式的_all_并分支到完整的请求路径(或进行大量的单个超量提取)来解决此问题,但这会很快变得笨拙,并且与分别声明每个页面实际上并没有什么不同。

这也是Relay也与react-router不兼容的同样原因,并且您不能指责facebook.com不是复杂的网站。

与Next路由器一起使用的主要成功策略是依靠可组合性(无论如何,这是现代React的驱动趋势),它使您可以重复使用组件而无需进行大量重复操作,同时还具有能够提取其所有数据的高效SSR (通过getInitialProps ),然后再与React渲染器进行对话。

我觉得走树的性能损失似乎过高了。 如今,许多生产应用程序都使用Apollo来执行此操作,这似乎还不错。

另外,如果您确实想减轻服务器的工作量,也可以CDN缓存您的响应。

当然,我只是指出了为什么React-router(AFAICT)在其当前实现中与Next根本不兼容的主要原因。 很多网站根本不需要性能,这是人们在冷启动时间很短的情况下愉快地使用免费的Heroku测功机所证明的(我想强调的是,我对某些网站也没有这么礼貌地说,可以完美匹配)。 但是,如果Next在性能上不太积极,则它们将不会在某些使用它的较大公司中流行,因为这些公司会关心服务器响应时间明显变慢。 如果对某些站点不关心,人们甚至在一个渲染完成之前就不会使用(并迫切等待改进)React的流式渲染器开始响应,更不用说两个了。

您绝对可以CDN缓存您的响应,但这消除了许多个性化/登录选项(因为这是您要降低点击率或将部分页面呈现给客户端的价格的折衷方案)。 如果可以使用CDN缓存整个应用程序,则最好使用CRA和react-snapshot并完全避免使用服务器。 这不一定是服务器要执行多少工作的问题,而是响应请求需要多长时间。

与Apollo这样的框架相比,它是一个很好的例子,它强调了易用性而不是性能,而与诸如Relay之类的更自以为是的/注重性能的框架相比。 都是频谱。

是的,我想这很公平。 但是我很好奇,看看remix.run的结果如何,也许他们会想出一种新颖的方法来使其与react-router 。 是的,嵌套路由不是强制性的,但是您必须同意,使内部UI的某些部分随路由而变化比拥有不同的页面并以不同的布局包装每个页面更为直观。

从下一个版本9.3开始,除了getServerSideProps之外,还有getStaticPaths可以帮助框架发现具有路径参数的预渲染路径。 也许可以对react-router采取类似的方法。

@merryweather :“下一步是在考虑性能的基础上构建的,服务器端react-router的主要性能含义是必须先遍历DOM树,然后才能知道要渲染的内容”

幼稚的问题:一旦在客户端上运行代码,您是否可以仅渲染顶级链接并获取/预取/缓存。 如果您不知道客户端将导航至何处,遍历服务器上的DOM树是否有意义?

天真的工作场景:当客户端请求URL时,仅呈现顶级链接和默认的活动链接内容,并根据请求ajax /获取其他所有内容(或在页面加载后在后台预取)...其他所有内容都包括所有较低级别的内容路线...漂洗并重复...?

@laurencefass,但即使是顶级链接也都在代码中,必须被发现对吗? 或者,您是说将文件系统路由与react-router一起使用,以便可以发现顶级链接?

@ avin-kavish我不是回答实施细节的最佳人选,但在客户端上只需要呈现初始屏幕内容:顶级链接+默认内容。 我认为其他任何事情在首次加载时都是多余的。 那么,为什么要在服务器上遍历DOM?

Next.js的主要问题不是路由器,而是具有getInitialPropsgetServerPropsgetStaticProps的数据获取模式。 为什么呢因为它破坏了需要它的组件的数据隔离。 例如,您要获取菜单的数据,您将从哪里获取数据? 我不知道。 诸如pages类的顶级组件对此一无所知,对吧?

Next.js的主要问题不是路由器,而是具有getInitialPropsgetServerPropsgetStaticProps的数据获取模式。 为什么呢因为它破坏了需要它的组件的数据隔离。 例如,您要获取菜单的数据,您将从哪里获取数据? 我不知道。 诸如pages类的顶级组件对此一无所知,对吧?

请详细说明一下。 什么是替代解决方案?

@lishine我很抱歉在这里有点题外话,但是在大多数情况下,我看不到Router是这里的主要问题。 Next.js路由器是好的,声明性的,约定优于配置。 我唯一无法在Next.js中使用的是数据获取方法,例如getInitialProps ,...
在我的应用中,每个组件都需要在同一位置,同一文件中声明其自己的数据,无论它是graphql还是rest。
“首页”组件仅用于组成子组件,而获取数据不是其工作。 子组件必须获取自身的数据,而不是其父数据。

为了清楚起见,这是我用于应用程序的代码示例:

const query = `
{
  result:users(
    where:{
      _and:[{
        active:{
          _eq:true
        }
      }, {
        is_exam_manager:{
          _eq:true
        }
      }]
    },
    order_by:{
      created_at:desc_nulls_last
    }
  ){
    id
    key:id
    user_code
    first_name
    last_name
    password
    active
  }
}
`
const Main = (props: any) => {
  const {
    data: { result }
  } = props
  return (
    <div>
      <Add title={'Add user'} role={'exam_manager'} />
      <Table
        columns={columns}
        dataSource={result}
        bordered={true}
        size={'small'}
      />
    </div>
  )
}
const MainWithData = graphql(query)(Main)
export default MainWithData

如您所见,您只有一个组件具有自己的数据。 您可以将其放置在任何位置。

当然,您可以毫无问题地使用Next.js模式,但就我而言,我更喜欢尽可能地隔离数据和组件,以便于以后维护和重构。

在我的应用中,每个组件都需要在同一位置,同一文件中声明其自己的数据,无论它是graphql还是rest。
“首页”组件仅用于组成子组件,而获取数据不是其工作。 子组件必须获取自身的数据,而不是其父数据。

我以相同的方式使用它。
所以您不使用SSR提取...
那么人们实际上是如何使用Next.js进行SSR提取的呢?

@linshine ,我们必须在首页级别下载所需的任何内容。

@lishine我很抱歉在这里有点题外话,但是在大多数情况下,我看不到Router是这里的主要问题。 Next.js路由器是好的,声明性的,约定优于配置。 我唯一无法在Next.js中使用的是数据获取方法,例如getInitialProps ,...
在我的应用中,每个组件都需要在同一位置,同一文件中声明其自己的数据,无论它是graphql还是rest。
“首页”组件仅用于组成子组件,而获取数据不是其工作。 子组件必须获取自身的数据,而不是其父数据。

为了清楚起见,这是我用于应用程序的代码示例:

...

如您所见,您只有一个组件具有自己的数据。 您可以将其放置在任何位置。

当然,您可以毫无问题地使用Next.js模式,但就我而言,我更喜欢尽可能地隔离数据和组件,以便于以后维护和重构。

@ revskill10为什么您不能让子级声明它的数据片段,然后让父级将其包含在顶级查询中? 特别是当您创建更多与孩子相关的片段时,您将拥有完美的数据隔离。 拥有带有子片段的父查询与在JSX中声明该子对象没有什么不同,因此您具有相同的耦合级别,但要避免请求瀑布(可悲的是,在REST中要困难得多)。

我们有一个Relay-Next应用程序,这种模式可以很好地工作,并具有数据封装和可重用的构成,并且我们可以轻松利用getInitialProps

@merrywhether更不用说much harder in REST ,您的方法有一个问题,即您无法确定哪个fragments是SSG / SSR还是CSR。
在我的方法中,就像使用{ noSSR: true/false}导入该组件一样简单。

我发现与供应商特定的路由库的锁定非常令人担忧,该路由库没有与任何主要路由库共享基础实现。

我最近对Next.js进行了评估,以评估它是否应该用作为当前客户端构建的许多前端应用程序之间共享的公共核心的基础。 尽管Next.js具有潜力; 该路由器是我最终拒绝Next.js并保留CRA作为这些应用程序基础的主要原因之一。

我确实理解使用react-router / @reach/router基于组件的顶级API作为SSR的基础的困难。 但这不是完全实现自定义基础实现的良好理由。 Gatsby的SSG与Next.js具有相同的关注点,并且具有基于半相似文件的路由结构。 但据我了解,盖茨比在幕后使用@reach/router为其路由实现提供动力,而不是重新发明轮子或暴露与其他库使用的Link API不兼容的Link API。

@dantman请问您为Next.js替代品选择了什么。 假设您需要服务器端渲染...。我一直在尝试After.js,如果zeit不支持的话,它可以为在Next.js中实现提供一些启发/想法。

@dantman请问您为Next.js替代品选择了什么。 假设您需要服务器端渲染...。我一直在尝试After.js,如果zeit不支持的话,它可以为在Next.js中实现提供一些启发/想法。

抱歉,我对您没有帮助。 SSR并不是硬性要求,因此我们只是继续使用CRA,而CRA是用来构建原型的。

我认为Next.js有望成为通用框架,因为它最近获得了混合SSR / SSG /仅客户端页面的功能,并且可以作为同构应用程序或静态/ PWA应用程序运行。 WebPack的定制很诱人,因为CRA一直在努力使用globalize-compiler。 Next.js服务器是中立/肯定的,因为无论如何我们都需要一个用于GraphQL / REST桥的API服务器。 SSR / SSG的选择是一个积极的选择,因为我正在构建将要基于六个应用程序的核心,而且将来可能会有用。 但是,Next.js的SSR的工作方式也存在一些问题,这些积极因素不值得由路由器引起的麻烦。

@丹特曼

我发现与供应商特定的路由库的锁定非常令人担忧,该路由库没有与任何主要路由库共享基础实现。

由于其出色的稳定性和“产品/市场适应性”作为“锁定”,使用一个在3年内未发生变化的API来限定开源组件是很奇怪的

Next.js已经成功并继续显示它的增长是由于它的路由器而不是尽管如此。

正如许多人在Twitter上看到我的评论一样,曾几何时,我们认真地考虑了在某些路由器中的合并(尽管我对哪个是您心目中的标准,到达或响应路由器以及哪个主要版本感到困惑)。 但是世界将我们引向了其他有趣的方向。 实际上,我们甚至不知道添加它有什么意义,因为每个人都在继续使用Next.js并开发出色的产品。

当我确实向人们打听为什么他们想要一个不同的路由器API时,出现频率最高的原因是人们对建立在路由器上的自家种植的框架解决方案感到困惑和沮丧,他们迫不及待地迁移到Next。 。 这不是植根于产品设计的原因。

当我说Next因为它的路由器而成功时,是因为它消除了两个问题:
1️⃣必须选择路由器的想法。 我们回想起来,这是一个极好的决定。 一直以来,具有稳定路由器的Next.js一直存在,路由器世界已经分裂并启动了各种API更改

2️⃣路由器的学习曲线。 已经提供了许多有关路由的讲习班和教程,但是Next.js文件系统优先的路由需要2秒钟的解释,并为您提供了构建令人难以置信的内容的平台,并且您可以直接进行产品开发。

我想强调最后一点。 考虑一下建立在Next.js上的世界上最新,发展最快的网站之一TikTok.com。 该网站的整个路由拓扑可以用那两个第二学习曲线来解释。 https://www.tiktok.com/@sheezus.christ/video/6824007862197439750pages/[user]/video/[id].jshttps://www.tiktok.com/trendingpages/trending.js

您提到喜欢的许多Next.js最新创新,例如混合静态/ SSG / SSR,也由我们的路由器设计实现。 实际上,该路由器还将启用将来将要进行的许多其他类似优化,以向客户端提供更少的JS。

但是,Next.js的SSR的工作方式也存在一些问题,这些积极因素不值得由路由器引起的麻烦。

很想听听这些。 上面的示例由Next.js混合静态/ SSR提供支持,我们看到了全面成功!

这真是一个有趣的话题。 Next具有避免瀑布式路由(又称为react-router和朋友)的具体原因,因为getInitialProps可以进行许多性能优化,而Next的方法正在变得非常流行,特别是因为某些人特别希望这些优化。 性能是设计权衡的结果,有时您可能会选择设计而不是性能,但这并不会使工具出错,对您来说对于特定项目而言是错误的。

最终,react-router并不是路由解决方案的全部。 它具有优点和缺点,与Next一样。 FWIW,Facebook不使用react-router,他们可能对使用React有所了解。 因此,有其他选择是很好的,实际上是JS生态系统的一大优点:让不同的事物在思想领域竞争,最终我们都前进。

由于我要解决的问题是,我想明确地说,我们总是愿意接受有关路由功能的评论,功能请求和错误报告。

理想情况下,这些将由产品驱动(“我需要做X,但是不可能”或“ Y是可能的,但不符合人体工程学”)。 我们一直在寻求改进,以帮助您制作具有良好用户体验的精益网站和应用程序🤗

@rauchg您能否解释在链接中拥有两个道具hrefas的原因? 为什么不能根据as prop的值推断预期的页面?

例如,在express中,如果我有一条路由为/blog/:slug ,我可以向/blog/hello-world发送一个http请求,并期望路由器路由到它。 我不必将/blog/:slugblog/hello-world发送到服务器。

@ avin-kavish这是一个很好的问题。 URL显示内容和要加载的页面之间有一个重要的区别。 实际上,TikTok使用它来渲染模态中的某些内容,即刷新页面时会变成其他页面。 但是,这里需要改进的一大方面是,我们可能应该静态地强制您引用文件系统中存在的有效页面。 我们将通过对此进行讨论并标记您的身份来跟进!

我认为该https://github.com/zeit/next.js/issues/8207已经存在一个问题

如果有人通过“嵌套路由”功能(如“嵌套路由”功能)观看此问题,该功能允许导航到新页面而无需像我以前那样重新呈现所有内容,则实际上存在一个专门的问题可供您观察和投票。 我刚刚发现了一个: https :

@rauchg

需要明确指出的是,我的主要问题不是缺少RR /到达样式组件API,我可以使用基于SSR的基于文件/配置的API。 尽管我有点乐观,但未来Suspense可以使替代SSR /路由API可行。 我的主要问题是路由器是完全定制的,在实现中的所有常见问题都需要重新实现,而不是与更广泛的React社区的任何部分共享。

我发现盖茨比的方法是可以接受的。 他们有一个具有SSG功能的基于文件+配置的路由API,并导出了自己的增强的Link组件。 但他们使用@reach/router来驱动基础实现。

我发现与供应商特定的路由库的锁定非常令人担忧,该路由库没有与任何主要路由库共享基础实现。

由于其出色的稳定性和“产品/市场适应性”作为“锁定”,使用一个在3年内未发生变化的API来限定开源组件是很奇怪的

路由器本质上与Next.js绑定。 出于一个原因采用Next.js意味着被绑定到路由器。 如果我们采用Next.js,后来又发现next / router的局限性导致我们正在尝试做的事情变得残废,那么绝对没有合理的逃生舱口。 “锁定”是一个很好的描述。

单独锁定不会成为主要问题。 盖茨比对@reach/router的使用也会被锁定。 但是@reach/router仅在盖茨比之外使用。 我不必单靠Gatsby社区来维护整个路由器堆栈。 我可以相信,有一个更大的社区依赖它,并且有更多的涉众(特定于路由堆栈)参与其中以确保其得到维护,解决棘手的路由问题(例如可访问性),并受到范围更广的社区的依赖,可能会分享我们将来可能遇到的任何潜在的严重问题。

尽管我对您认为哪一个是您的标准是Reach或React Router以及哪个主要版本感到困惑

根据事实上的标准, <Link>应该是什么样子。 Reach和React Router(RR)都共享非常相似的API。 例如<Link to='/about'>About</Link>在RR和Reach中均有效(当然,扩展名是Gatsby)。 这使得Next.js的特有<Link href='/about'><a>About</a></Link>更具冲击性。

就我认为Next.js应该使用的内容而言。 我并不局限于特定的库,如果Next.js已经在使用一个库,我不建议切换到另一个库。 我主要关心的是,路由实现与Next.js之外具有更大社区的库共享。

在实践中,这相对来说没有意义。 到目前为止,除了RR和Reach之外,我还没有看到具有大型用户群的任何React路由器。 而且RR和Reach将成为一个库,因此无论您以最终结果开始还是一样。

我前一段时间尝试了Next,但是路由器缺乏灵活性,这使我发现了一个名为After.js https://github.com/jaredpalmer/after.js?utm_source=hashnode.com的Razzle实现

由于React Router只是一个包,我们不能导入它并将渲染仅限于客户端,因此它像需要它的SPA一样工作并为我们提供嵌套的组件路由吗? React Router是否只是一组可能(可能)嵌入页面中并与其他组件一样加载Next.js页面路由器的组件?

我在较早的线程中读到,zeit计划集成RR,今天仍然如此吗?

为什么我们不允许在next.js路由器中使用嵌套路由作为最后的选择,并明确指出这些区域不会被预先渲染。 至少,这将节省我们的工作量,避免了当我们希望页面中的子资源根据路线更改时不可避免地要编写的if条件。

我要对这个问题投赞成票。

另一个没有提到的优点是,RR具有更高的可测试性(AFAIK没有用于路由器测试的官方nextjs API),它具有用于封装测试和故事的MemoryRouter。

Next.js具有许多良好的功能(自动WebPack,静态文件和TypeScript,例如CRA,但不仅限于PWA; API路由;无服务器支持,快速刷新,甚至对Web +本地应用程序都具有实验性的Expo支持)和核心即使SSR和SSG的API并不是很好。 但是,尽管内置路由系统和SSR / SSG可以用于某些环境; 对于其他人,它们则阻碍了开发,因为两种API的限制都为上述项目提供了错误的权衡。

妥协如何? Next.js已经有插件。 如果不从内部替换路由器,而是将路由器和SSR API(即路由文件中的getStaticProps / getServerSideProps )与Next.js的核心分开,该怎么办? 例如,我们可以将最基本的核心部分放在@next/core然后将当前使用的路由器和get*Props API移至@next/router 。 为了简化和向后兼容, next可以是重新导出@next/core的框架,并预先配置了Vercel的首选路由器。 但是,社区可能会开发出具有折衷方案的路由器和SSR / SSG API,这些折衷方案更适合于那些项目,否则该项目将被大量使用,浪费了Next.js的优势。

关于Next.js核心需要路由器插件提供什么的一些想法:

  • 给定一个请求{url,body等},核心将期望路由器插件将该请求呈现给文档(字符串或流)或引发响应(即404或重定向)。
  • 在导出时,核心将期望路由器插件提供需要呈现的页面列表。

@next/router可能会通过以下方式通过api实现相同的模式:

  • 给定一个请求,确定负责的路由文件并正常渲染
  • 在客户端上执行与当前不知道何时调用SSR API并呈现所需路由的操作类似的操作(可能将基于API的SSR API移至正常的API路由)
  • 导出时使用页面文件树和getStaticPaths提供静态页面列表

我可能会看到自己尝试使用带有@apollo/react-ssr React Router v6和带有react-ssr-prepassreact@experimental Suspense的路由器插件。 它放弃了同构SSR路由的仅SSR路由,并在不限制get*Props样式API的情况下实现了SSR / SSG。

我意识到的是,可以在不破坏当前API的情况下实现嵌套路由+ SSG。 因此,目前我们有getStaticPaths ,我们可以用它来暗示嵌套的路线以进行预渲染。 例如,

给定路线/foo/[...slug]

function FooPage() {

  return (
      <Switch>
          <Route path="/foo/bar">
              <SomeResource />
              <Route path={`${parenthPath}/baz`} component={SomeSubResource} />
          </Route>
          .... more routes
      </Switch>
  )
}

可以预先渲染

export async function getStaticPaths() {

  return {
    paths: [
      { slug: [ 'bar' ] },
      { slug: [ 'bar', 'baz' ] },
    ],
  }
}

到目前为止,next.js就像服务器端框架一样,具有在React中创建页面的便利。 它不像react-router那样强大。 如上所述,基于目录的路由可能会在构建面向消费者的站点(如tiktok)中占有一席之地,但是对于复杂的数据驱动的应用程序门户,嵌套路由仍然是最主要的。 这就是为什么首先创建单页面应用程序的原因,它允许更改UI的位而不必替换整个页面。 可以很方便地利用它来对资源-子资源关系进行建模。 就目前而言,如果我要建立像电子商务网站这样的消费者网站的公共页面,我可以使用next.js ,但是当我需要建立诸如admin,买卖双方门户之类的私有区域时,切换到CRA。

@ avin-kavish的主要问题不是使其正常运行,而是使其得以优化:Next.js上的每个页面默认都有自己的捆绑软件,并针对速度进行了优化。

如果像您一样在单个页面中开始添加大量内容/子内容,那么最终可能会得到一个很大的捆绑包(本质上这并不“糟糕”,但是您应该注意权衡)。 您可能可以使用next/dynamic想法进行一些手动优化:)

@rauchg唯一的维度不是下一个路由器的好坏。 另一个非常重要的事情是往返于next.js和社区支持的迁移,并且https://github.com/vercel/next.js/issues/1632#issuecomment -633310614讲得很好。 Next.js是一种很好的解决方案,用于抽象出高质量SSR应用程序所需的许多样板,因此,它是许多Web应用程序非常诱人的迁移目标。 现在的问题是,它需要完整的路由重写,以便迁移到next.js,如果需要,也可以重写。

@dantman早些时候建议的可插拔路由可以非常优雅地解决此问题,并且不需要任何人推销其原则😉

react-router(和任何嵌套的路由解决方案)的问题在于,它会使静态分析变得更加困难,因为如果不运行(或模拟)代码本身就无法获得任何特定URL的相关代码路径。 接下来,不仅仅是“将用户界面放在网页上”框架,这就是为什么他们与Chrome团队合作创建更加高度优化的捆绑策略的原因。

react-router用户习惯于直接使用react-loadable,因为它rr完全将责任委托给了最终用户,但是Next试图抽象化和自动化这并不容易。 所提出的可插拔路由器方法可能必须涉及到为框架提供大量构建时间信息的路由器插件,以实现相同类型的输出,因为每个路由器都必须知道如何根据其自身的模式生成此类信息。

纯粹是推测,但我想React结束Suspense时很多事情处于困境,因为在库中建立一流的模式将极大地影响所有路由器库,并为构建异步/可加载的基础提供具体的基础捆绑模式。

长话短说/总结如下:没有“一刀切”的解决方案。 一切都有权衡。 Next.js当前做事的每一个“优势”都会带来不利。 每个项目的优缺点是最重要的。 因此,推荐使用可插拔路由器/ ssg / ssr体系结构。 不同的项目需要不同的东西,现在,Next.js仅适用于权衡优先级与Next.js中硬编码方式一致的项目。

react-router(和任何嵌套的路由解决方案)的问题在于,它会使静态分析变得更加困难,因为如果不运行(或模拟)代码本身就无法获得任何特定URL的相关代码路径。

老实说,这仅在您使用SSG并具有一堆非动态路由时才重要。 如果您的所有路由都是SSG或仅用于客户端,则没有用。 而且,如果您的大多数路线都是动态的,则无论如何都必须使用getStaticPaths明确声明它们。 这与在假设的Next.js插件中明确定义路由的工作量相同,该插件仅使用未经修改的原始react-router并要求您明确定义静态路由。

当然,这是一个优势,有些团队会想要这样做。 但是,这只是Next.js潜在用户的一个子组。 还有其他一些团体可能想要RR或其他路由库提供的某些优势,并且需要明确声明静态路由是可以接受的折衷方案,也可以是非问题。 例如,我的最后几个项目是那种B2B / B2C应用程序,其中100%的内容都在登录页面后面,并且静态呈现任何内容都没有意义。 与CRA相比,Next.js具有一些优势,这使Next.js更可取。 但是像路由器这样的东西是很大的危险信号,我们只是继续使用CRA。 这些项目本来非常适合带有原始react-router的Ne​​xt.js。

这还假设每个不想next/router都想使用JSX形式的react-router。 这不是next/router替代的唯一类型。

路由器的另一种类型是Gatsby.js样式。 在项目仍使用基于文件系统的页面结构的地方,但是内部是通过另一个路由库(例如react-router)实现的(Gatsby在内部使用@reach/router )。 这种路由器插件将为您提供相同的静态分析优势。 但这也将为您提供替代路由器与嵌套路由无关的任何优势。 例如,适应路由API的潜在偏好,更好地处理可访问性,更好地集成到该路由器周围的生态系统中。

当然,即使在react-router生态系统中,JSX表格也不是使用react-router的唯一方法。 也有react-router-config 。 这很容易进行静态分析,还支持嵌套路由。

react-router用户习惯于直接使用react-loadable,因为它rr完全将责任委托给了最终用户,但是Next试图抽象化和自动化这并不容易。

我们中的一些人可以自行处理代码拆分。 嵌套的路由对项目比自动代码拆分更为重要。 这就是最适合项目的权衡因素。

这更多是一个旁注,但是我实际上对babel / webpack插件的潜力感到好奇,该插件会自动对路由执行此操作。

另外,react-loadable是一个有效的已失效的库(自发布以来已有2年,不接受错误报告)。 就我个人而言,我宁愿手动使用@loadable/components进行代码拆分,而不是使用基于react-loadable内部派生的Next.js自动内置的东西。

所提出的可插拔路由器方法可能必须涉及到为框架提供大量构建时间信息的路由器插件,以实现相同类型的输出,因为每个路由器都必须知道如何根据其自身的模式生成此类信息。

对。 通常,这就是插件系统的工作方式。 老实说,插件可以提供这种信息是一个优势,而不是问题。 将其包含在插件中意味着Next.js收集此信息的方式不适合某些类型的项目需求,可以将其替换为适合那些项目需求的信息。 但是无需分叉并重写所有Next.js即可。

纯粹是推测,但我想React结束Suspense时很多事情处于困境,因为在库中建立一流的模式将极大地影响所有路由器库,并为构建异步/可加载的基础提供具体的基础捆绑模式。

实际上,在可插拔路由器系统上运行时,这本身可能是一个很好的论据。 现在,由于所有路由和SSR内容都已硬编码到Next.js中,因此无法轻松地对Next.js中任何类型的未来路由系统进行实验。 暂挂如何影响Next.js的路由和其他路由库? 如果没有派生和重写Next.js的大块代码,您将无法进行尝试(至少在Next.js的SSR和捆绑方面)。

路由器插件将是进行此类实验的好地方。 只要插件API是低级别够将有可能到餐桌只是next/router插件,并尝试写一个反应@实验是路由器+悬疑基础版本。 而且由于这是一个插件(不是Next.js的全部分支),因此可以轻松地选择参与实验并测试新的基于Suspense的路由器。 这一点现在很重要,而不是后来,因为这种实验是为什么react @ experimental存在的原因,以便从实际项目中收集反馈。

@dantman我不会不同意您所说的话。 它是所有关于权衡的问题。 最大的折衷是Next团队花费时间的时间。 到目前为止,低配置高性能SSR似乎一直是他们的主要关注点。 我确实知道这不一定对所有用户都适用,但这是Next最初用来脱颖而出的角度(这就是我们在工作中选择它们的原因)。 由于Gatsby和Jamstack的流行,它们最近对SSG进行了更多挖掘,但它们仍然是SSR imo的最佳选择。

坦白说,只有在您使用SSG并拥有大量非动态路线时,这才有意义

我不确定您的意思是什么,因为SSG与SSR对尝试为第一页(“关键路径” JS)提供尽可能小的JS有效负载(实际上不是动态路由)并不重要。 通常,对于SSR应用程序来说,最小化关键路径资产非常重要(因此付出了所有努力),对此表示赞赏。 老实说,如果您只使用登录墙的CSR应用程序,那么与CRA相比,Next _does_会有很多缺点(SSR永远不会像CSR那样方便)。 听起来好像您是在为真正的性能赢家而打折那些实际上正在执行运行时SSR(带有服务器端处理登录/个性化功能)的应用。 并非所有内容都适合SSG与CSR的二分法。

我们中的一些人可以自行处理代码拆分

我们中有些人自己也有能力处理webpack,react-dom / server等。 到目前为止,Next的目标似乎是像CRA一样使这种弹出现象越来越少。 没错,我应该说类似react-loadable,因为在该空间中有许多解决方案,并且它们仅从中继(如Relay)中出现的数据加代码模式中变得更加奇特。

最终,我不会不同意可插拔路由器系统可能会很好。 我只是指出,Next团队要删除框架的核心原则(例如捆绑拆分逻辑)并将其提取到可插入架构中,将需要大量工作。 我的猜测突出了一个事实,即我不想开始为我的库设计一个基础性的更改,而对核心依赖项的新更改可能会轻易颠覆该更改。 我当然同意Next的设计存在某些局限性,但就目前的设计约束而言,这些局限性在大多数情况下是有意义的。

坦白说,只有在您使用SSG并拥有大量非动态路线时,这才有意义

我不确定您的意思是什么,因为SSG与SSR对尝试为第一页(“关键路径” JS)提供尽可能小的JS有效负载(实际上不是动态路由)并不重要。

我们可能在考虑不同的原因,为什么需要静态分析存在的路由的能力。 假设我们都将“静态分析”称为“仅通过阅读代码即可在构建时识别路径列表(例如['/about', '/', '/profile'] )的能力”。

听起来您在谈论某种类型的JS包优化? 我没有在文档中找到任何相关信息,因此我不知道您在考虑基于静态路由分析的确切类型的优化。

我的想法是,对路线的这种静态分析主要对SSG有用。 即因为在构建站点时存在pages/about.js文件,所以Next.js知道存在/about路由,并且它需要为该路由预呈现html,即使您从未明确告诉过它有/about路径可以进行预渲染。

SSR不需要预构建的html,因为它仅在请求进入时才这样做(此时,它会运行代码并具有一个渲染路径)。 客户端渲染的页面根本没有预渲染的html。 而且,如果您的SSG页面是动态的,则无论如何都需要声明所有路径。 因此我的想法。

老实说,如果您只使用登录墙的CSR应用程序,那么与CRA相比,Next _does_会有很多缺点(SSR永远不会像CSR那样方便)。

您在Next.js中想到的关于CSR应用程序的不利之处是什么? 除了上述路由器问题。

据我了解,Next.js支持SSR / SSG / CSR路由的全部范围。 因此,据说它仍然适合编写仅登录登录CSR的应用程序。

就个人而言,我的观点绝对是某些人编写的,大部分是CSR应用程序,偶尔有SSR和SSG需求,希望为我的所有项目提供一个功能强大的工具包,而又不需要他们需要什么SSR / SSG / CSR的组合。

根据我的经验,即使在仅使用CSR的应用程序中,CRA也有很多缺点,这可能会使Next.js的CSR页面更具优势。 WebPack配置自定义而不弹出是一个很大的问题。 当我在向应用程序添加i18n时不能简单地使用globalize-compiler WebPack插件时,这给我带来了很多痛苦。 即使大多数页面是CSR,也可以选择加入特定页面的SSR / SSG,这也是一个优势(例如,您99.9%的页面是CSR且位于登录页面之后;但是您拥有登录页面以及条款/联系方式您要启用SSG或SSR的页面)。 用CRA之类的东西无法合理地做任何这些事情。

我们中的一些人可以自行处理代码拆分

我们中有些人自己也有能力处理webpack,react-dom / server等。 到目前为止,Next的目标似乎是像CRA那样使这种弹射越来越少

坦白地说,手动执行基于路由的代码拆分(确保通过React.lazy或替代库,而不是直接导入来修改您的路由组件以使用路由组件)与手动管理自定义WebPack配置或编写脚本相距甚远您自己的带有react-dom/server的SSR处理程序。

不想手动编写整个WebPack配置或自定义SSR服务器是完全合理的(即想使用Next.js之类的广泛使用的框架),但仍然可以使用react-router并手动执行基于路由的代码-分裂。 特别是如果选择自动路由基础代码拆分意味着失去正在使用的广泛使用的路由器库,并且使用缺少某些功能的路由器,那么与其他用途广泛的路由器相比,API可能需要的功能与其他路由器完全不同。

我一直在寻找不需要将react-router与NextJS集成而无需创建自定义服务器的方法时遇到此问题,因此我决定尝试一下。

使用react-router v6(测试版),创建自定义_app

// _app.js || _app.tsx
import * as React from 'react'
import App from 'next/app'
import NextRouter from 'next/router'

export default class CustomApp extends App {
    render() {
        const { Component, pageProps } = this.props

        if (process.browser) {
            const { Router } = require('react-router-dom')
            const { createMemoryHistory } = require('history')
            const history = createMemoryHistory({
                initialEntries: [this.props.router.asPath],
            })

            history.listen(function ({ action, location }) {
                const url = {
                    hash: location.hash,
                    pathname: location.pathname,
                    search: location.search,
                }
                switch (action) {
                    case 'PUSH':
                        return NextRouter.push(url)
                    case 'REPLACE':
                        return NextRouter.replace(url)
                    default:
                        return void 0
                }
            })

            return (
                <Router location={history.location} navigator={history} action={history.action}>
                    <Component {...pageProps} />
                </Router>
            )
        } else {
            const { StaticRouter } = require('react-router-dom/server')
            return (
                <StaticRouter location={this.props.router.asPath}>
                    <Component {...pageProps} />
                </StaticRouter>
            )
        }
    }
}

为什么

在NextJS中管理(可选捕获所有路由)不是一件容易的事(例如: /foo/[[...bar]].js ),因此我正在探索一种能够在此类页面上使用react-router的方法。 也许其他人有不同的原因,但这是我主要关心的问题,并且react-router提供了一个不错的API,特别是在当前处于beta版的v6中。

这个怎么运作

它只是创建一个自定义MemoryRouter而不是BrowserRouter因此我们不会因为拥有NextJS路由器和NextJS路由器而弄乱了浏览器的历史记录。 它侦听PUSHREPLACE的内存历史记录更改,因此您可以使用react-router钩子或Link进行导航,但在后台调用NextJS路由器方法.push.replace

需要调用NextJS路由器方法,否则路由更改实际上不会触发NextJS get*Props方法。 换句话说,它与使用NextJS Link shallow选项类似。 使用react-routerLink的缺点是没有prefetch 。 但是,您仍然可以改用NextJS Link并且react-router仍然可以对路由更改做出反应。

有趣的是,您现在可以利用NextJS dynamicreact-router路由并执行以下操作:

// /foo/[[...bar]].js
import * as React from 'react'
import { Route, Routes } from 'react-router-dom'
import dynamic from 'next/dynamic'

const Home = dynamic(() => import('src/views/Home'))
const About = dynamic(() => import('src/views/About'))
const Navigation = dynamic(() => import('src/views/Navigation'))

export default function Root() {
    return (
        <>
            <Navigation />
            <Routes>
                <Route path="/foo/" element={<Home />} />
                <Route path="/foo/about" element={<About />} />
            </Routes>
        </>
    )
}

无论如何,我希望这对某人有帮助。 我尚未在生产中使用此代码,此代码来自我在当地的游乐场,因此可能有些事情可以改进,但这只是一个开始。

将React Router与Next.js 9.5+结合使用

如果您使用Next.js 9.5或更高版本的正确的方式做,这是重新写入。 _请勿使用自定义服务器_! 这里有一个有关如何执行此操作的详细教程: https :

基本思路:

  1. 创建一个自定义应用程序( /pages/_app.tsx

  2. 如果typeof window === "undefined"返回null typeof window === "undefined" 。 这是必需的,以防止在SSR步骤中反应路由器抛出错误!

// pages/_app.tsx

import { AppProps } from 'next/app';

function App({ Component, pageProps }: AppProps) {
  return (
    <div suppressHydrationWarning>
      {typeof window === 'undefined' ? null : <Component {...pageProps} />}
    </div>
  );
}

export default App;

suppressHydrationWarning属性用于防止服务器渲染的内容与客户端渲染的内容不一致时,React引发警告。

  1. 重写所有路由到主页
// next.config.js

module.exports = {
  async rewrites() {
    return [
      // Rewrite everything else to use `pages/index`
      {
        source: '/:path*',
        destination: '/',
      },
    ];
  },
};

然后您可以像平常一样使用React Router! 链接的教程中有很多上下文/解释,但这可以帮助您入门。 https://vriad.com/essays/building-a-spa-with-nextjs

@colinhacks好的解决方案可以确认它是否有效。 需要考虑的事情可能是将应用程序移至自己的页面,例如app.js或route.js等。 然后将其重写为

// next.config.js

module.exports = {
  async rewrites() {
    return [
      {
        source: '/app/:path*',
        destination: '/app',
      },
    ];
  },
};

只需考虑一下,您的解决方案就是我发现的最佳解决方案。

此页面是否有帮助?
0 / 5 - 0 等级