App Engine 服务与 apollo-express-server v2.x.x 静态服务 React 应用程序

App Engine service with apollo-express-server v2.x.x serving React app statically

这与其说是问题,不如说是知识问题。我一直在深入研究 GAE 的文档、Youtube 视频和帖子,了解如何从单个 App Engine 服务提供完整的 MERN stack 应用程序。

老实说,我对 App Engine 部署在幕后做了什么并没有很详细的了解,但我知道它会在 8080 端口从默认端口公开您的服务分配的路线(即 https://xxxxxxxx.uc.r.appspot.com)。

基于这些知识,我认为完全有可能静态地提供一个构建的 React 应用程序并通过 /graphql 端点处理来自同一应用程序的传入查询。

例如:

  1. 这解决了 CORS,因为所有东西都具有相同的来源。
  2. 您将自己限制在一个 App Engine 服务上,这样您就可以继续使用免费层级服务:)

这是我的项目结构:

root/
 app/
  node_modules/
  build/ <----- React app built
  src/
  App.js
  index.js
  ...
 server/ <----- In here is the Apollo Express Server v2.x.x serving app/build generated above^
  index.js
 package.json
 node_modules/
 app.yaml <---- This file tells App Engine what to do and which routes to expose
 ...

我的app.yaml

runtime: nodejs12

env_variables:
  PORT: 4000

handlers:
  - url: /
    static_files: app/build/index.html
    upload: app/build/index.html
  - url: /
    static_dir: app/build
  - url: /graphql
    script: auto <---- Supposedly App Engine is smart enough to understand what to do with this route.

我只是无法从服务到 React 应用程序查询我的 App Engine 服务。

有谁知道我正在做的事情是否可行,或者根本无法配置带有 Apollo Server 的 App Engine 以服务于静态 webapp + 同时公开 /graphql 端点。

非常欢迎任何建议或想法!

--------------------------------更新------------ ----------------------

根据GAEfan的建议,我更新了app.yaml文件:

好吧!我认为这确实有效,我只是在控制台上仍然收到一些关于 resources not found 的错误所以,这是 build/

的内部结构
build/
 static/
  css/
  js/
 asset-manifest.json
 favicon.ico
 index.html
 logo192.png
 manifest.json
 robots.txt
 service-worker.js

我已经以同样的方式向此建议添加了 json|txt|map|ico 资源。

- url: /(.*\.(gif|png|jpg|css|js|json|txt|map|ico))$
  static_files: app/build/
  upload: app/build/.*\.(gif|png|jpg|css|js|json|txt|map|ico)$

这解决了找不到资源的问题。并且您的通配符已经解析了 /graphql 端点。出于某种原因,未正确建立 WebSocket 握手,但我不确定这是 App Engine 的直接限制,还是协议默认被阻止。

有人了解 App Engine 上的 Websockets 吗?

还有更多问题,但我会将其添加为 partial/temporary 答案...

app.yaml 中的前 2 个 url 处理程序是重复的。 URL 处理匹配第一个,并将所有内容发送到 ...index.html。我假设您在构建目录中有一些 jscss 或其他静态文件。这些将永远不会提供给浏览器。因此,您需要使用更好的正则表达式路由、通配符等。

让我们一次做这些:

handlers:
  - url: /$  # this '$' ends the match, so the url matches only the root domain
    static_files: app/build/index.html
    upload: app/build/index.html

接下来,让我们测试 .js.css 等:

- url: /(.*\.(gif|png|jpg|css|js))$
  static_files: app/build/
  upload: app/build/.*\.(gif|png|jpg|css|js)$

然后(假设您 graphql 正常工作,您可以将所有其他请求发送到那里:

- url: /graphql
  script: auto

甚至:

- url: /(.*) # catches everything else!
  script: auto

显示您的 /build 目录中的文件或目录树,我们可以确保我们已经说明了所有内容。