这对我来说很难完全正确。很少通过谷歌的指导方式。我希望这有助于其他人。
正如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-routing路由设置GAE app.yaml会产生“意外令牌<”错误。
在开发环境中,所有路由在直接调用时都有效。 localhost:5000和localhost:5000 / test产生预期的结果。
在GAE标准中,当直接调用URL www.test-app.com时,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会产生错误“意外的令牌<”。看来它将.js文件作为index.html提供。
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: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" alt="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
当请求进入其URL路径时,将与handlers
文件的app.yaml
部分中指定的模式进行比较,按照指定的顺序进行比较。第一个匹配获胜并且执行匹配的处理程序指定的任何内容。一旦掌握了这一点,就不再需要猜测发生了什么。
所以你要向www.test-app.com
和www.test-app.com/test
提出请求,它们分别转换为/
和/test
URL路径。
使用你的第一个app.yaml
(注意你的模式是相同的,第二个永远不会匹配):
/
匹配第一个模式,你的app目录中的静态build/index.html
(不是.js文件!)将被返回/test
与任何模式都不匹配,404将被退回与你的第二个app.yaml
:
/
匹配第一个模式,再次返回静态build
文件我怀疑你的app目录中的/test
文件是你进行部署的地方(整个build/index.html
dir是作为静态dir上传的)在你进行部署时有HTML语法错误(这就是冻结的方式 - 它是静态的),导致您看到的错误消息。
您可能已经修复了自部署以来文件的本地副本,这可以解释为什么它现在似乎在本地工作。如果是这样,重新部署应用程序也应该解决GAE上的问题。
更新:
我不认为您需要为build/index.html
设置静态处理程序 - 它将始终在部署时为本地工作空间中该文件中的任何内容提供服务。
我将遵循官方build
的非静态示例(使用build/index.html
模式更新而不是app.yaml Configuration File原始模式以确定它与.*
匹配):
/.*
甚至有可能完全放弃/
部分,我没有在几个handlers:
- url: .*
script: auto
示例中看到一个:
我从appengine/memcached/app.standard.yaml和appengine/storage/standard/app.yaml那里得到了答案,并将它们浓缩到下面的app.yaml中。它似乎适用于GAE标准的React SPA。不需要应用程序服务器(例如:serve.js,ExpressJS等)。
Nathan Shephard