手动刷新或写入时,React-router网址不起作用

2020/09/21 23:01 · javascript ·  · 0评论

我正在使用React-router,当我单击链接按钮时,它可以正常工作,但是当我刷新网页时,它不会加载我想要的内容。

例如,我进去了localhost/joblist,一切都很好,因为我按链接到达这里。但是,如果刷新网页,则会得到:

Cannot GET /joblist

默认情况下,它不是这样工作的。最初,我的URL为localhost/#/localhost/#/joblist并且它们工作正常。但是我不喜欢这种URL,因此尝试删除它#,我写道:

Router.run(routes, Router.HistoryLocation, function (Handler) {
 React.render(<Handler/>, document.body);
});

这个问题不会发生localhost/,这个总是返回我想要的。

编辑:这个程序是单页的,所以/joblist不需要向任何服务器询问任何内容。

EDIT2:我的整个路由器。

var routes = (
    <Route name="app" path="/" handler={App}>
        <Route name="joblist" path="/joblist" handler={JobList}/>
        <DefaultRoute handler={Dashboard}/>
        <NotFoundRoute handler={NotFound}/>
    </Route>
);

Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});

查看有关已接受答案的评论以及该问题的一般性质(“不起作用”),我认为这可能是对此处涉及的问题进行一些一般性解释的好地方。因此,此答案旨在作为OP的特定用例的背景信息/阐述。请多多包涵。

服务器端与客户端

首先要了解的是,现在有2个地方可以解释URL,而在“过去”中,以前只有1个地方。过去,当生活很简单时,一些用户向http://example.com/about服务器发送了一个请求,服务器检查了URL的路径部分,确定该用户正在请求About页面,然后将该页面发回。

使用客户端路由(这是React-Router提供的功能),事情就变得不那么简单了。首先,客户端尚未加载任何JS代码。因此,第一个请求将始终是服务器。然后,这将返回一个页面,其中包含用于加载React和React Router等所需的脚本标签。仅在加载了这些脚本后,阶段2才会启动。在第2阶段中,例如,当用户单击“关于我们”导航链接时,URL 本地更改http://example.com/about(由History API实现),但未向服务器发出请求相反,React Router在客户端执行其操作,确定要渲染的React视图并进行渲染。假设您的About页面不需要进行任何REST调用,那么它已经完成了。您已从首页转换为关于我们,而没有触发任何服务器请求。

因此,基本上,当您单击链接时,将运行一些Javascript来操纵地址栏中的URL,而不会导致页面刷新,这又导致React Router 在客户端执行页面转换

但是,现在考虑如果将URL复制粘贴到地址栏中并将其通过电子邮件发送给朋友,会发生什么情况。您的朋友尚未加载您的网站。换句话说,她仍处于阶段1她的机器上还没有运行React Router。所以,她的浏览器将使服务器的请求http://example.com/about

这就是您麻烦的开始。到现在为止,您只需将静态HTML放置在服务器的webroot上就可以摆脱困境。但这会在从服务器请求时404为所有其他URL 提供错误这些相同的URL 在客户端可以正常工作,因为那里的React Router正在为您进行路由,但是除非您使服务器理解它们,否则它们在服务器端将失败

结合服务器端和客户端路由

如果希望http://example.com/aboutURL在服务器端和客户端上都可以使用,则需要在服务器端和客户端上为其设置路由。有道理吧?

这就是您开始选择的地方。解决方案的范围从完全绕过问题(通过返回引导HTML的包罗万象的路线)到完全同构的方法(在该方法中,服务器和客户端都运行相同的JS代码)。

完全绕开该问题:哈希历史记录

使用哈希历史记录而不是浏览器历史记录,“关于”页面的URL看起来像这样:
http://example.com/#/about
哈希(
#)符号后面的部分不会发送到服务器。因此,服务器仅http://example.com/按预期方式看到并发送索引页。React-Router将拾取#/about零件并显示正确的页面。

缺点

  • “丑陋”的网址
  • 使用这种方法无法进行服务器端渲染。就搜索引擎优化(SEO)而言,您的网站只包含一个页面,几乎没有任何内容。

包罗万象

通过这种方法,您确实使用了浏览器历史记录,但是只是在发送/*的服务器上设置了一个包罗万象index.html,有效地为您提供了与哈希历史记录相同的情况。但是,您确实拥有干净的URL,以后可以改进此方案而不必使所有用户的收藏夹无效。

缺点

  • 设置更复杂
  • 仍然没有好的SEO

杂种

在混合方法中,您可以通过为特定路由添加特定脚本来扩展包罗万象的方案。您可以制作一些简单的PHP脚本来返回包含内容的网站最重要页面,以便Googlebot至少可以看到页面上的内容。

缺点

  • 设置起来更加复杂
  • 对于那些给予特殊待遇的路线,只有好的SEO
  • 复制代码以在服务器和客户端上呈现内容

同构

如果我们使用Node JS作为服务器,以便我们可以在两端运行相同的 JS代码怎么办?现在,我们所有的路由都在一个react-router配置中定义,我们不需要复制渲染代码。可以这么说,这是“圣杯”。如果客户端发生页面转换,服务器将发送与最终相同的标记。就SEO而言,此解决方案是最佳的。

缺点

  • 服务器必须(能够)运行JS。我已经尝试过Java icw Nashorn,但是它对我不起作用。实际上,这主要意味着您必须使用基于Node JS的服务器。
  • 许多棘手的环境问题(window在服务器端使用等)
  • 陡峭的学习曲线

我应该使用哪个?

选择一个您可以摆脱的。就我个人而言,我认为综合起来很简单,因此这是我的最低要求。通过此设置,您可以随着时间的流逝而改进。如果您已经使用Node JS作为服务器平台,那么我肯定会研究做一个同构的应用程序。是的,一开始很难,但是一旦掌握了它,它实际上是解决问题的一种非常优雅的方法。

因此,对我而言,基本上,这就是决定性因素。如果我的服务器在Node JS上运行,我将同构。否则,我会选择全包解决方案,并随着时间的推移和SEO要求对其进行扩展(混合解决方案)。

如果您想了解更多有关使用React进行同构(也称为“通用”)渲染的知识,那么有一些关于该主题的不错的教程:

另外,为使您入门,我建议您查看一些入门套件。选择一个与您选择的技术相匹配的技术(请记住,React只是MVC中的V,您需要更多的东西来构建完整的应用程序)。首先看一下Facebook本身发布的内容:

或从社区中选择许多。现在有一个不错的站点尝试对所有索引:

我从这些开始:

目前,我使用的是通用的自制版本,该版本受上述两个入门工具包的启发,但是现在它们已经过时了。

祝您一切顺利!

这里的答案都非常有帮助,对我有用的是配置Webpack服务器以期望路由。

devServer: {
   historyApiFallback: true,
   contentBase: './',
   hot: true
},

historyApiFallback是为我解决此问题的原因。现在,路由可以正常工作,我可以刷新页面或直接输入URL。无需担心节点服务器上的变通方法。该答案显然仅在使用webpack时有效。

编辑:这里是我的答案的更详细的原因,为什么这是必要的:https :
//stackoverflow.com/a/37622953/5217568

您可以更改.htaccess文件并插入以下内容:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]
</IfModule>

我正在使用react: "^16.12.0"并且react-router: "^5.1.2"
此方法是万能的,可能是入门的最简单方法。

对于React Router V4用户:

如果您尝试通过其他答案中提到的哈希历史记录技术来解决此问题,请注意,

<Router history={hashHistory} >

在V4中不起作用,请HashRouter改用:

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>

参考:HashRouter

我刚才使用create-react-app制作了一个网站,并在此处介绍了同样的问题。BrowserRoutingreact-router-dom包装中使用我在Nginx服务器上运行,为我解决的问题是在其中添加了以下内容/etc/nginx/yourconfig.conf

location / {
  if (!-e $request_filename){
    rewrite ^(.*)$ /index.html break;
  }
}

这对应于.htaccess在运行Appache的情况下将以下内容添加到

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

这似乎也是Facebook自己建议的解决方案,可以在这里找到

在index.html中head,添加以下内容:

<base href="/">
<!-- This must come before the css and javascripts -->

然后,当与webpack dev服务器一起运行时,请使用此命令。

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallback 是重要的部分

可以通过两种不同的方式调用路由器,具体取决于导航是在客户端还是在服务器上进行。您已将其配置为用于客户端操作。关键参数是运行方法的第二个参数,即位置。

当您使用React Router Link组件时,它将阻止浏览器导航并调用transitionTo进行客户端导航。您使用的是HistoryLocation,因此它使用HTML5历史记录API通过模拟地址栏中的新URL来完成导航的效果。如果您使用的是较旧的浏览器,则无法使用。您将需要使用HashLocation组件。

当您点击刷新时,您将绕过所有React和React Router代码。服务器收到请求,/joblist并且它必须返回某些内容。在服务器上,您需要将请求的路径传递给run方法,以使其呈现正确的视图。您可以使用相同的路线图,但可能需要对进行不同的调用Router.run正如Charles所指出的,您可以使用URL重写来处理此问题。另一个选择是使用node.js服务器来处理所有请求,并将路径值作为location参数传递。

例如,在快递中,它可能看起来像这样:

var app = express();

app.get('*', function (req, res) { // This wildcard method handles all requests

    Router.run(routes, req.path, function (Handler, state) {
        var element = React.createElement(Handler);
        var html = React.renderToString(element);
        res.render('main', { content: html });
    });
});

请注意,请求路径正在传递到run为此,您需要有一个服务器端视图引擎,您可以将呈现的HTML传递到该引擎。renderToString在服务器上使用React并在其中运行其他一些注意事项页面在服务器上呈现后,当您的应用加载到客户端时,它将再次呈现,并根据需要更新服务器端呈现的HTML。

如果您通过AWS Static S3 Hosting和CloudFront托管React应用

这个问题由CloudFront响应403 Access Denied消息来解决,因为它希望/ some / other / path存在于我的S3文件夹中,但是该路径仅存在于React的带有react-router的路由内部。

解决方案是设置分发错误页面规则。转到CloudFront设置,然后选择您的分配。接下来转到“错误页面”标签。单击“创建自定义错误响应”并添加403的条目,因为这是我们得到的错误状态代码。将“响应页面路径”设置为/index.html并将状态码设置为200。最终结果以其简单性令我惊讶。提供了索引页面,但URL保留在浏览器中,因此,一旦React应用加载,它将检测URL路径并导航到所需的路由。

错误页面403规则

这样可以解决你的问题

在生产模式下的ReactJS应用程序中,我也遇到了同样的问题。这是该问题的两种解决方案。

1.将路由历史更改为“ hashHistory”,而不是用browserHistory代替

<Router history={hashHistory} >
   <Route path="/home" component={Home} />
   <Route path="/aboutus" component={AboutUs} />
</Router>

现在使用命令构建应用

sudo npm run build

然后将build文件夹放在您的var / www /文件夹中,现在该应用程序可以正常工作,在每个URL中添加#标签。喜欢

本地主机/#/ home本地主机/#/ aboutus

解决方案2:如果没有#标签,则使用browserHistory,

在路由器中设置您的历史= {browserHistory},现在使用sudo npm run build对其进行构建。

您需要创建“ conf”文件来解决404 not found页面,conf文件应如下所示。

打开您的终端,键入以下命令

cd / etc / apache2 / sites-available ls nano sample.conf在其中添加以下内容。

<VirtualHost *:80>
    ServerAdmin admin@0.0.0.0
    ServerName 0.0.0.0
    ServerAlias 0.0.0.0
    DocumentRoot /var/www/html/

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    <Directory "/var/www/html/">
            Options Indexes FollowSymLinks
            AllowOverride all
            Require all granted
    </Directory>
</VirtualHost>

现在,您需要使用以下命令来启用sample.conf文件

cd /etc/apache2/sites-available
sudo a2ensite sample.conf

然后它将要求您使用sudo服务apache2重新加载或重新启动apache服务器

然后打开您的localhost / build文件夹并添加内容如下的.htaccess文件。

   RewriteEngine On
   RewriteBase /
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteRule ^.*$ / [L,QSA]

现在,该应用程序可以正常运行。

注意:将0.0.0.0 ip更改为您的本地IP地址。

如果对此有任何疑问,请随时提出评论。

希望对其他人有帮助。

Webpack Dev Server具有启用此功能的选项。打开package.json并添加--history-api-fallback该解决方案为我工作。

反应路由器教程

如果您在IIS上托管react应用,只需添加一个包含以下内容的web.config文件:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

这将告诉IIS服务器将主页返回到客户端,而不是404错误,并且不需要使用哈希历史记录。

如果您使用的是Create React App:

有一个伟大的步行路程,虽然这个问题与许多大型主机平台的解决方案,你可以找到这里的创建做出反应应用页面上。例如,我将React Router v4和Netlify用作前端代码。只需要在我的公用文件夹中添加一个文件(“ _redirects”),然后在该文件中添加一行代码即可:

/*  /index.html  200

现在,当输入浏览器或有人刷新时,我的网站可以正确呈现诸如mysite.com/pricing之类的路径。

将此添加到webpack.config.js

devServer: {
    historyApiFallback: true
}

生产堆栈:React,React Router v4,BrowswerRouter,Express,Nginx

1)用户BrowserRouter提供漂亮的网址

// app.js

import { BrowserRouter as Router } from 'react-router-dom'

const App = () {
  render() {
    return (
        <Router>
           // your routes here
        </Router>
    )
  }
}

2)使用将index.html添加到所有未知请求 /*

// server.js

app.get('/*', function(req, res) {   
  res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
    if (err) {
      res.status(500).send(err)
    }
  })
})

3)捆绑webpack与 webpack -p

4)运行nodemon server.jsnode server.js

编辑:您可能想让Nginx在服务器块中处理此问题,而忽略步骤2:

location / {
    try_files $uri /index.html;
}

尝试使用以下代码在公用文件夹内添加“ .htaccess”文件。

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

RewriteRule ^ /index.html [L]  

如果确实有index.html的备用版本,请确保在index.html文件中具有以下内容:

<script>
  System.config({ baseURL: '/' });
</script>

这可能因项目而异。

如果您使用的是Firebase,则只需确保在应用程序根目录(在托管部分中)的firebase.json文件中具有rewrites属性。

例如:

{ 
  "hosting": {
    "rewrites": [{
      "source":"**",
      "destination": "/index.html"
    }]    
  }
}

希望这可以节省别人的挫折感和浪费的时间。

祝您编程愉快...

关于该主题的进一步阅读:

https://firebase.google.com/docs/hosting/full-config#rewrites

Firebase CLI:“配置为单页应用程序(将所有URL重写为/index.html)”

我找到了带有React Router(Apache)的SPA解决方案。只需添加.htaccess

<IfModule mod_rewrite.c>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

来源:https : //gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042

我还没有使用服务器端渲染,但是遇到了与OP相同的问题,在大多数情况下,Link似乎都可以正常工作,但是当我有参数时失败了。我将在此处记录我的解决方案,以查看它是否对任何人都有帮助。

我的主要jsx包含以下内容:

<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />

这对于第一个匹配的链接来说效果很好,但是当:id更改<Link>嵌套在该模型的详细信息页面上的表达式时,URL在浏览器栏中发生更改,但是页面的内容最初并未更改以反映链接的模型。

麻烦的是我曾经用来props.params.id设置模型componentDidMount该组件仅安装一次,因此这意味着第一个模型是粘贴在页面上的模型,随后的链接会更改道具,但页面看起来没有变化。

将模型同时设置为组件状态componentDidMountcomponentWillReceiveProps基于组件状态(在此状态下基于下一个道具)可以解决该问题,并且页面内容会更改以反映所需的模型。

这个主题有点老了,已经解决了,但是我想向您推荐一个简单,清晰和更好的解决方案。如果您使用Web服务器,则可以使用。

每个Web服务器都具有在http 404的情况下将用户重定向到错误页面的功能。要解决此问题,您需要将用户重定向到索引页面。

如果使用Java基本服务器(tomcat或任何java应用程序服务器),则解决方案可能是以下几种:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- WELCOME FILE LIST -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <!-- ERROR PAGES DEFINITION -->
    <error-page>
        <error-code>404</error-code>
        <location>/index.jsp</location>
    </error-page>

</web-app>

例:

  • GET http://example.com/about
  • Web服务器抛出http 404,因为此页面在服务器端不存在
  • 错误页面配置告诉服务器将index.jsp页面发送回用户
  • 然后JS将在客户端上完成剩下的工作,因为客户端的网址仍然是http://example.com/about

就是这样,不再需要魔术:)

对于使用IIS 10的用户,这是您应该做的以实现此目的的方法。确保与此同时使用browserHistory。作为参考,我将给出用于路由的代码,但这并不重要,重要的是下面的组件代码之后的下一步:

class App extends Component {
    render() {
        return (
            <Router history={browserHistory}>
                <div>
                    <Root>
                        <Switch>
                            <Route exact path={"/"} component={Home} />    
                            <Route path={"/home"} component={Home} />
                            <Route path={"/createnewproject"} component={CreateNewProject} />
                            <Route path={"/projects"} component={Projects} />
                            <Route path="*" component={NotFoundRoute} />
                        </Switch>
                    </Root>
                </div>
            </Router>
        )
    }
}
render (<App />, window.document.getElementById("app"));

由于问题是IIS接收到来自客户端浏览器的请求,因此它将像请求页面一样解释URL,然后由于没有可用的页面而返回404页面。请执行下列操作:

  1. 打开IIS
  2. 展开服务器,然后打开站点文件夹
  3. 点击网站/应用程序
  4. 转到错误页面
  5. 打开列表中的404错误状态项
  6. 代替选项“将内容从静态文件插入错误响应”,将其更改为“在此站点上执行URL”,然后在URL中添加“ /”斜杠值。

现在它将正常工作。

在此处输入图片说明
在此处输入图片说明

希望对您有所帮助。:-)

如果您在后端使用Express或其他框架,则可以添加以下类似的配置,并在配置中签出Webpack公用路径,即使使用BrowserRouter,即使重新加载,它也可以正常工作

expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
});

修复刷新或直接调用URL时出现的“无法获取/ URL”错误。

配置您的webpack.config.js以使给定的链接像这样路由。

module.exports = {
  entry: './app/index.js',
  output: {
       path: path.join(__dirname, '/bundle'),
       filename: 'index_bundle.js',
       publicPath: '/'
  },

当我使用.Net Core MVC时,类似以下内容对我有所帮助:

    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            var url = Request.Path + Request.QueryString;
            return App(url);
        }

        [Route("App")]
        public IActionResult App(string url)
        {
            return View("/wwwroot/app/build/index.html");
        }
   }

基本上在MVC端,所有不匹配的路由都将落入Home/Index所指定的位置startup.cs在内部Index可以获取原始请求url并将其传递到任何需要的地方。

startup.cs

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });

如果您在IIS中托管;将此添加到我的webconfig中解决了我的问题

<httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
    <remove statusCode="500" subStatusCode="100" />
    <remove statusCode="500" subStatusCode="-1" />
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" path="/" responseMode="ExecuteURL" />
    <error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" />
    <error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" />
</httpErrors>

您可以对任何其他服务器进行类似的配置

使用ReduxHashRouter对我有用,只需替换:

import {
  Router //replace Router
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <Router history={history}> //replace here saying Router
            <Layout/>
        </Router>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();

至:

import {
  HashRouter //replaced with HashRouter
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <HashRouter history={history}> //replaced with HashRouter
            <Layout/>
        </HashRouter>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();

如果有任何人在这里寻找使用Laravel在React JS SPA上的解决方案。
公认的答案是为什么会发生此类问题的最好解释。
如前所述,您必须同时配置客户端和服务器端。在您的刀片模板中,包括js捆绑文件,确保
URL facade像这样使用

<script src="{{ URL::to('js/user/spa.js') }}"></script>

在您的路由中,确保将其添加到刀片模板所在的主要端点。例如,

Route::get('/setting-alerts', function () {
   return view('user.set-alerts');
});

以上是刀片模板的主要端点。现在也添加一条可选路线,

Route::get('/setting-alerts/{spa?}', function () {
  return view('user.set-alerts');
});

发生的问题是先加载刀片模板,然后再加载反应路由器。因此,当您加载时'/setting-alerts',它会加载html和js。但是,当您加载时'/setting-alerts/about',它将首先在服务器端加载。由于在服务器端,此位置上没有任何内容,因此找不到该返回值。当您拥有该可选路由器时,它将加载该页面,并且还加载了react路由器,然后react loader确定要显示的组件。希望这可以帮助。

我正在使用WebPack,遇到同样的问题解决方案=>在您的server.js文件中

const express = require('express');
const app = express();

app.use(express.static(path.resolve(__dirname, '../dist')));
  app.get('*', function (req, res) {
    res.sendFile(path.resolve(__dirname, '../dist/index.html'));
    // res.end();
  });

为什么我的应用程序刷新后不呈现?

您可以尝试阅读所有内容,尽管这不是我的:

https://www.andreasreiterer.at/fix-browserrouter-on-apache/

修复应用程序的路由现在,这里是最终修复路由的方法。要告诉Apache将请求重定向到应用程序所在的index.html,我们必须修改.htaccess文件。如果您的应用程序文件夹中还没有此类文件,则只需创建它即可。

然后确保您输入的这4行将神奇地使您的路由工作。

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

将.htaccess文件放入与index.html相同的目录后,Apache会将每个新请求直接重定向到您的应用程序。

奖励:将React应用程序部署到子目录

如果要将应用程序部署到子目录中,那么可以通过例如https://myapp.com/the-app进行访问,您很快就会注意到还有另一个问题。每次单击新路径都会将URL转换为https://myapp.com/route-abc之类的内容 -重新加载后将再次中断。但是有一个简单的解决方法:

BrowserRouter有一个名为basename的道具,您可以在其中指定子目录路径:

从现在开始,每条类似/ contacts的路线都会产生一个类似http://myapp.com/the-app/contacts的URL

I had this same problem and this solution worked for us..

Background:

We are hosting multiple apps on the same server. When we would refresh the server would not understand where to look for our index in the dist folder for that particular app. The above link will take you to what worked for us... Hope this helps, as we have spent quite a hours on figuring out a solution for our needs.

We are using:

package.json

"dependencies": {
"babel-polyfill": "^6.23.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"prop-types": "^15.5.6",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-persist": "^4.6.0",
"redux-thunk": "^2.2.0",
"webpack": "^2.4.1"
}

my webpack.config.js

webpack.config.js

/* eslint-disable */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const babelPolyfill = require('babel-polyfill');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/views/index.html',
  filename: 'index.html',
  inject: 'body'
});

module.exports = {
  entry: [
    'babel-polyfill', './app/index.js'
  ],
  output: {
    path: __dirname + '/dist/your_app_name_here',
    filename: 'index_bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      loader: 'babel-loader',
      query : {
          presets : ["env", "react", "stage-1"]
      },
      exclude: /node_modules/
    }]
  },
  plugins: [HTMLWebpackPluginConfig]
}

my index.js

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import Routes from './Routes'
import { Provider } from 'react-redux'
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import configureStore from './store/configureStore'
import { syncHistoryWithStore } from 'react-router-redux'
import { persistStore } from 'redux-persist'

const store = configureStore();

const browserHistory = useRouterHistory(createHistory) ({
  basename: '/your_app_name_here'
})
const history = syncHistoryWithStore(browserHistory, store)

persistStore(store, {blacklist: ['routing']}, () => {
  console.log('rehydration complete')
})
// persistStore(store).purge()


ReactDOM.render(
    <Provider store={store}>
      <div>
        <Routes history={history} />
      </div>
    </Provider>,
  document.getElementById('mount')
)

my app.js

var express = require('express');
var app = express();

app.use(express.static(__dirname + '/dist'));
// app.use(express.static(__dirname + '/app/assets'));
app.set('views', __dirname + '/dist/your_app_name_here');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

app.get('/*', function (req, res) {
    res.render('index');
});

app.listen(8081, function () {
  console.log('MD listening on port 8081!');
});
本文地址:http://javascript.askforanswer.com/shoudongshuaxinhuoxierushireact-routerwangzhibuqizuoyong.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!