目前答案
这对我来说很难做到完全正确。很少通过谷歌提供指导。我希望这能帮助其他人。
正如丹·科尼莱斯库所指出的,教练们接受第一场比赛。所以我们从更具体到不那么具体。我通过以下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路由器路由设置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生成错误"Unexpected token<"。它似乎正在以index.html.的形式提供.js文件
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.0npm: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
我们如何说服应用程序引擎允许react SPA直接处理路线
我从Nathan Shephard和Dan Cornelescu那里得到了答案,并将它们浓缩到下面的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
当请求进入其URL路径时,将按照指定的顺序将其与app.yaml
文件的handlers
部分中指定的模式进行比较。第一场比赛获胜,并且执行匹配处理程序指定的任何内容。一旦你掌握了这一点,就没有必要再猜测发生了什么
因此,您正在向www.test-app.com
和www.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
的静态处理程序——它将始终在部署时为本地工作区中该文件中的任何内容提供服务。
我会遵循官方app.yaml配置文件中的非静态示例(用.*
模式而不是/.*
原始模式更新,以确保它也与/
匹配):
handlers:
- url: .*
script: auto
甚至可能完全删除handlers
部分,我在几个Node.js示例中看不到一个repo示例:
- appengine/datastore/app.standard.yaml
- appengine/memcached/app.standard.yaml
- appengine/storage/standard/app.yaml
我在这方面花了一些时间,这非常适合我在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
在使用谷歌应用引擎、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,所以如果是这样的话,请确保将其更改为构建
对我来说,以下设置做得很好:
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