如何在 GAE 中设置路由以进行反应?在基本 create-react-app 上的 GAE 中,通过 URL 直接路由到 react-router-dom 路由失败?

Posted

技术标签:

【中文标题】如何在 GAE 中设置路由以进行反应?在基本 create-react-app 上的 GAE 中,通过 URL 直接路由到 react-router-dom 路由失败?【英文标题】:How do I setup routing for react in GAE? Directly routing to react-router-dom routes via URL fails in GAE on basic create-react-app? 【发布时间】:2019-06-12 08:42:48 【问题描述】:

暂时回答

这对我来说很难完全正确。通过谷歌的指导方式很少。我希望这对其他人有所帮助。

正如 Dan Cornilescu 指出的那样,处理程序接受了第一场比赛。所以我们从更具体到不太具体。我按照npm run build 创建的文件夹结构解决了这个问题: 1.处理js、css和media的子目录。 2. 处理 manifest.json 和 fav.ico 的 json 和 ico 请求。 3. 将所有其他流量路由到 index.html

handlers:
  - url: /static/js/(.*)
    static_files: build/static/js/\1
    upload: build/static/js/(.*)
  - url: /static/css/(.*)
    static_files: build/static/css/\1
    upload: build/static/css/(.*)
  - url: /static/media/(.*)
    static_files: build/static/media/\1
    upload: build/static/media/(.*)
  - url: /(.*\.(json|ico))$
    static_files: build/\1
    upload: build/.*\.(json|ico)$
  - url: /
    static_files: build/index.html
    upload: build/index.html
  - url: /.*
    static_files: build/index.html
    upload: build/index.html

欢迎提供更有效的答案。

原问题:

为 react-router 路由设置 GAE app.yaml 会产生“Unexpected token

在开发环境中,所有路由都在直接调用时起作用。 localhost:5000 和 localhost:5000/test 产生预期的结果。

在直接调用 URL www.test-app.com 时根目录的 GAE 标准 app.yaml 函数中。 www.test-app.com/test 产生 404 错误。

app.yaml #1

runtime: nodejs8
instance_class: F1
automatic_scaling:
  max_instances: 1

handlers:
  - url: /
    static_files: build/index.html
    upload: build/index.html

将 app.yaml 配置为接受通配符路由对于所有路径都失败。 www.test-app.com/ 和 www.test-app.com/test 产生错误“Unexpected token

app.yaml #2

runtime: nodejs8
instance_class: F1
automatic_scaling:
  max_instances: 1

handlers:
  - url: /.*
    static_files: build/index.html
    upload: build/index.html

重现此问题的步骤:

节点:10.15.0 npm:6.4.1

gcloud init 通过 Google Cloud SDK

npm init react-app test-app

npm install react-router-dom

将路由器添加到 index.js:

index.js

import BrowserRouter as Router, Route from 'react-router-dom';
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';


ReactDOM.render(
  <Router>
    <App />
  </Router>,
  document.getElementById('root'));
serviceWorker.unregister();

向 app.js 添加路由:

app.js

import Route from 'react-router-dom'
import React,  Component  from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component 
  render() 
    return (
      <div>
        <Route exact path="/"
          render=() =>  <div className="App">
            <header className="App-header">
              <img src=logo className="App-logo"  />
              <p>
                Edit <code>src/App.js</code> and save to reload.
              </p>
              <a
                className="App-link"
                href="https://reactjs.org"
                target="_blank"
                rel="noopener noreferrer"
              >
                Learn React
              </a>
            </header>
          </div> />
        <Route exact path="/test"
          render=() =>  <div className="App">
            Hello, World!
          </div> />
      </div>
    );
  


export default App;

package.json 没有变化:

package.json


  "name": "test-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": 
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "react-router-dom": "^4.3.1",
    "react-scripts": "2.1.3"
  ,
  "scripts": 
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  ,
  "eslintConfig": 
    "extends": "react-app"
  ,
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]

npm run build

gcloud app deploy

我们如何说服应用引擎允许 React SPA 直接处理路由?

【问题讨论】:

在运行时它说它是 nodejs8 这是否意味着加载其反应 index.html 的 nodejs? 据我所知,这是正确的。 node.js 通过 index.html 提供响应。 是的,我刚刚在 GAE 中签入了文档,因此要进行 spa / 反应,nodejs 必须加载文件,并将路由设置为全部指向 index.html Ex router.get('/*', (req, res) =&gt; res.sendFile(path.join(__dirname, '../../build', 'index.html')) ); 。现在如何在我不再知道的 GAE 设置中进行设置,在使用 nodejs 和 reactjs 进行部署时,我总是手动设置。 谢谢。这与我发现的响应类似。但我不知道这段代码去哪里了。在我看来,这就像服务器端代码,比如 express。这对我来说是一个困惑点。我有一个运行快递的服务,但我的反应内容不是从那里提供的。 是的,我明白了,从 GEA 阅读文档在我看来就是这样,nodejs 运行一个 express 并加载它的 index.html,关键是要更改服务器内部的配置。跨度> 【参考方案1】:

我从Nathan Shephard 和Dan Cornilescu 中得到答案,并将它们浓缩到下面的app.yaml 中。它似乎适用于我在 GAE 标准上的 React SPA。不需要应用程序服务器(例如:serve.js、ExpressJS 等)。

env: standard
runtime: nodejs10
service: default

handlers:
  - url: /static
    static_dir: build/static

  - url: /(.*\.(json|ico|js))$
    static_files: build/\1
    upload: build/.*\.(json|ico|js)$

  - url: .*
    static_files: build/index.html
    upload: build/index.html

【讨论】:

完美的例子! 完美运行。【参考方案2】:

当请求进入其 URL 路径时,将按照指定的顺序将其与 app.yaml 文件的 handlers 部分中指定的模式进行比较。第一个匹配获胜,匹配处理程序指定的任何内容都会被执行。一旦掌握了这一点,就无需再猜测发生了什么。

所以您正在向www.test-app.comwww.test-app.com/test 发出请求,它们分别转换为//test URL 路径。

你的第一个app.yaml(注意你的模式是相同的,第二个永远不会匹配):

/ 匹配第一个模式,将返回您应用目录中的静态 build/index.html(不是 .js 文件!) /test 不匹配任何模式,将返回 404

与您的第二个app.yaml

/ 匹配第二种模式,将提供静态 build 目录(我认为它会触发您的节点应用程序,但我不确定 - 我不是节点用户) /test 匹配第一个模式,同样会返回静态 build/index.html 文件

我怀疑您进行部署的应用目录中的 build/index.html 文件(整个 build 目录已作为静态目录上传)在您进行部署时存在 HTML 语法错误(就是这样被冻结 - 它是静态的),导致您看到错误消息。

可能自部署以来已修复文件的本地副本,这可以解释为什么它现在似乎在本地工作。如果是这样,重新部署应用程序也应该可以解决 GAE 上的问题。

更新:

我认为您不希望为您的build/index.html 使用 static 处理程序 - 它始终会在部署时提供本地工作区中该文件中的任何内容。

我会遵循官方 app.yaml Configuration File 中的 非静态 示例(更新为 .* 模式而不是 /.* 原始模式,以确保它与 / 匹配好):

handlers:
- url: .*
  script: auto

甚至可以完全删除handlers 部分,我在几个Node.js samples repo 示例中看不到一个:

appengine/datastore/app.standard.yaml appengine/memcached/app.standard.yaml appengine/storage/standard/app.yaml

【讨论】:

我已根据从您的回答中收集到的内容更新了主帖中的 app.yaml 文件。我相信,所有的路径都是为了去同一个地方。由于它是一个带路由的单页应用程序,所有路径都指向同一个 build/index.html。当模式是 / 它工作得很好。当模式是 /.* 它应该匹配所有内容并产生相同的结果?但事实并非如此,这就是我的困惑所在。 我不确定/.* 是否匹配/。我只使用.*,它确实匹配/【参考方案3】:

我在这方面花了一些时间,这非常适合我在 GAE 标准上的 React CRA。

runtime: nodejs10
service: bbi-staging
env: standard
instance_class: F2
handlers:
  - url: /(.*\.(gif|media|json|ico|eot|ttf|woff|woff2|png|jpg|css|js))$
    static_files: build/\1
    upload: build/(.*)
  - url: /(.*)
    static_files: build/index.html
    upload: build/index.html

【讨论】:

【参考方案4】:

在使用 Google App Engine、webpack 和 app.yaml 度过了美好的一天之后,以下是对我有用的配置:

webpack.js(只有相关的 json 部分,即模块的规则):

  
    test: /\.(png|jpg|gif)$/,
    use: [
    
      loader: 'url-loader',
      options: 
        name: '[name].[ext]',
        outputPath: 'media/',
        limit: 8192
      
    
    ]
  ,
  
    test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
    use: [
    
      loader: 'file-loader',
      options: 
        name: '[name].[ext]',
        outputPath: 'fonts/'
      
    
    ]
  ,

app.yaml

runtime: nodejs10 
handlers:
  - url: /(.*\.(png|ico|jpg|gif))$
    static_files: dist/\1
    upload: dist/.*\.(png|ico|jpg|gif)$
  - url: /fonts/(.*\.(woff|woff2))$
    static_files: dist/fonts/\1
    upload: dist/fonts/.*\.(woff|woff2)$
  - url: /html.js
    static_files: dist/html.js
    upload: dist/html.js
  - url: /javascript.js
    static_files: dist/javascript.js
    upload: dist/javascript.js
  - url: /.*
    static_files: dist/index.html
    upload: dist/index.html
    secure: always
    redirect_http_response_code: 301
  - url: /
    static_dir: dist

注意:我的输出目录是 dist,所以如果是这种情况,请确保将其更改为 build

【讨论】:

【参考方案5】:

对我来说,以下设置效果很好:

runtime: nodejs16
service: development

handlers:
  - url: /static
    secure: always
    static_dir: build/static

  - url: /(.*\.(gif|media|json|ico|eot|ttf|woff|woff2|png|jpg|css|js|svg))$
    secure: always
    static_files: build/\1
    upload: build/.*\.(gif|media|json|ico|eot|ttf|woff|woff2|png|jpg|css|js|svg)$

  - url: .*
    secure: always
    static_files: build/index.html
    upload: build/index.html

【讨论】:

以上是关于如何在 GAE 中设置路由以进行反应?在基本 create-react-app 上的 GAE 中,通过 URL 直接路由到 react-router-dom 路由失败?的主要内容,如果未能解决你的问题,请参考以下文章

如何允许快速后端 REST API 在使用 axios 的反应前端中设置 cookie?

如何在CodeIgniter中设置动态路由以使用slug?

我可以在 react-router 中设置基本路由吗

如何在反应中设置 cookie?

如何在反应中设置来自axios的响应状态

cisco设备如何在RIPv2协议中设置默认路由?