文章
问答
冒泡
nextjs的路径和react-router-dom的混合使用

我们在使用nextjs作为react服务端渲染的时候,一般情况下,只有使用nextjs的文件夹路径作为url地址就可以了。但是,如果有部分页面我们不想用服务端渲染,这部分页面可以使用单页应用来做。

那么问题来了,服务端渲染和单页应用怎么融合?首先,我们看理论上是否可行,单页应用,就是在一个服务端渲染的页面上,通过HashRoute来控制页面的展示,那么我们就用其中一个页面来做这个单页应用的载体好了。

1.首先我们以HashRoute来测试,按照正常的react-router-dom模式来写。
layout

const UserLayout = ({route})=>{
    return <>
        <NormalAppBar/>
        <Link to={`/article-collections`}>article-collections</Link>
        <div>{renderRoutes(route.routes)}</div>
    </>
}
export default UserLayout



articles页面

const UserArticles = ({route})=>{
    return <>article</>
}
export default UserArticles;



article-collections页面

const UserArticleCollections = ({route})=>{
    return <>article collections</>
}
export default UserArticleCollections



routes.js

export default [
    {
        path: '/', component: UserLayout, routes: [
            {path: '/article-collections', component: UserArticleCollections},
            {path: '/', component: UserArticles},
        ]
    }
]



user,这个页面就类似单页应用的index文件,由于页面是服务端渲染的,所以不需要render到元素下

import React from "react";
import {
    HashRouter as Router
} from 'react-router-dom';
import {renderRoutes} from 'react-router-config';
import userRoutes from "./routes/user"

const UserView = () => {
    return <>
        <Router>{renderRoutes(userRoutes)}</Router>
    </>
}
export default UserView



在pages/user/index.jsx下把组件加载进来

import React from "react";
import dynamic from "next/dynamic";
const UserView = dynamic(()=>import('../../app/views/user/index'),{ ssr: false }) //此处一定是动态加载,不要服务端渲染

const UserPage = ()=>{
    return <>
        <UserView/>
    </>
}
export default UserPage



下面看下效果
WX20201015-114222@2x.pngimage6.png



可见react-router-dom是生效了。

2.但是如果不是管理后台的话,我们一般不会使用hashRoute来作为路径的,所以,我们还是要改成BrowserRouter模式。我们知道,在webpack-dev-server作为web服务的时候,是需要配置 historyApiFallback 的,historyApiFallback的作用就是把请求都指向index.html页面。那么我们根据这个思路,调整下配置。
next.config.js

async rewrites() {
    return [
        {
            source: '/user/:path*',
            destination:'/user'
        },
    ]
},



同时routes也要做相应的调整,改成全路径

export default [
    {
        path: '/', component: UserLayout, routes: [
            {path: '/user/article-collections', component: UserArticleCollections},
            {path: '/', component: UserArticles},
        ]
    }
]



看下效果
image8.pngimage7.png

达到期望。

另外,如果既想用react-router-dom 又想要ssr,要怎么办呢?
在react-router里还有一个StaticRouter 这个是不需要dom的,所以我们可以如下操作

import React from "react";
import {StaticRouter} from 'react-router';

import {BrowserRouter} from 'react-router-dom';
import UserView from "../../frontend/views/user";

const isServer = (typeof window === 'undefined')

const UserPage = ({visitor, owner}) => {
    return <>
        {isServer && <StaticRouter>
            <UserView visitor={visitor} owner={owner}/>
        </StaticRouter>}
        {!isServer && <BrowserRouter>
            <UserView visitor={visitor} owner={owner}/>
        </BrowserRouter>}
    </>
}



判断是否是服务端渲染,客户端和服务端采用两套机制。

next.js
react-router-dom
ssr

关于作者

落雁沙
非典型码农
获得点赞
文章被阅读