I have a nodejs backend and an angular frontend app in the same folder. The angular app outputs the build files to a static folder and nodejs uses the following to load the html file
//Idiomatic expression in express to route and respond to a client request
app.get('/', (req, res) => { //get requests to the root ("/") will route here
res.sendFile(process.cwd()+"/angularApp/static/index.html") //server responds by sending the index.html file to the client's browser
//the .sendFile method needs the absolute path to the file, see: https://expressjs.com/en/4x/api.html#res.sendFile
});
This is my app.yaml for nodejs :
runtime: nodejs16
handlers:
- url: /
static_files: angularApp/static/index.html
upload: angularApp/static/index.html
- url: /
static_dir: angularApp/static
However when I deploy the app to GCP I get the following errors in the console
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
What should the app.yaml file contain?
Tou can take a look of how docker works. Basically, you put your dependencies and source code into an image, then you ca easily deploy it on google cloud platform https://cloud.google.com/run/docs/deploying .
Related
I am trying to deploy the react app on gcloud. The app builds and starts normally when I do it locally.
If I npm start from gcloud console it's also available.
The problem is that when I build the app and deploy it to App Engine, the redirects does not work.
I have a google sign in added to the page but when I click Sign In, instead of redirecting, page says that the URL was not found and the url string after {app-url}/ consists of the contents of index.html.
I have tried different variations of the app.yaml file. The one I'm using right now looks like this.
runtime: nodejs16
handlers:
# Serve all static files with url ending with a file extension
- url: /(.*\..+)$
static_files: build/\1
upload: build/(.*\..+)$
# Catch all handler to index.html
- url: /.*
static_files: build/index.html
upload: build/index.html
I'm a noob to gcloud so would appreciate any help.
Thanks
I have a node.js server that serves the built static files of my create-react-app at /admin. The problem is that anytime I make a change to my react app I have to build the files over again to see the updates. Instead, I'd like to proxy requests for my frontend at /admin to my dev server that comes with create-react-app, running at localhost:3000, because this would allow for a much faster development experience.
This is what my server looks like now:
// app.ts
...
const app: Koa = new Koa();
app.use(mount('/admin', serve(__dirname + '/build')));
...
And this is what I tried:
import proxy from 'koa-better-http-proxy';
const app: Koa = new Koa();
app.use(
mount(
'/admin',
proxy('localhost:3000', {})
)
)
What ends up happening is the requests for static files still go out and the response gives an index.html file but the JS doesn't seem to run and it gives me errors:
Uncaught SyntaxError: Unexpected token '<'
I've also played around with the proxy header settings to adjust content-type to application/json but I had no success there either.
Due to the environment, I cannot just run the node server in one terminal and the react app in another. The request comes from a verified 3rd party and must go through my node server first before being served the frontend portion of my app.
I created following express API
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
require("dotenv/config");
//routes
const authRoute = require("./routes/auth.js");
const adminRoute = require("./routes/admin.js");
//middleweres
//converting body into json using body parser
app.use(cookieParser());
app.use(bodyParser.json());
app.use("/", express.static("public"));
app.use("/api/auth", authRoute);
app.use("/api/admin", adminRoute);
// starting express server
// app.listen(5000, () => {
// console.log("listning on port 5000");
// });
module.exports = {
app,
};
in public folder I have html file and css and js inside public/static folders
html, css and js in public folder are generated with react build.
I am trying to deploy this API in google cloud function with following command
gcloud functions deploy outreach-dashboard --entry-point app --runtime nodejs10 --trigger-http --allow-unauthenticated
function is getting deployed but problem is when I see the function on gcp dashboard it source does not contain public folder and if I download source as zip then I can see public folder there but its empty.
I need public folder to get deployed so I can serve it using
express.static("public")
You are trying to serve several endpoints in the same Cloud Functions. I saw some hack on Stack overflow where folks bend the framework to achieve this. It's not my recommendation.
Cloud Run is a very similar platform. The same underlying infrastructure, and feature very close (I wrote an article on this). But you serve a containerize webserver, more suitable for your use case.
You can easily have a try on it.
Uncomment your "starting app express" part
Test locally if it works.
Then run this command
gcloud beta run deploy outreach-dashboard --source=. --platform=managed --region=us-central1 --allow-unauthenticated
change the region if needed
The command :
upload the sources (take care of your .gitignore and .gcloudignore file to be sure to upload all the files)
Create a container with your source. To achieve this, Buildpacks.io is used. Exactly the same process that with Cloud Functions and App Engine.
Deploy the container on Cloud Run.
If the problem persist, there is may an issue with the automatic container build process (maybe some file are automatically discarded). In this case, you can write a very simple Dockerfile similar to this one that you have in the getting started documentation.
This time, you can create and deploy in 2 steps (and 2 commands)
# create the container with Cloud Build based on the docker file
gcloud builds submit --tag gcr.io/<PROJECT_ID>/<containerName>
# Deploy on Cloud Run
gcloud beta run deploy outreach-dashboard --image=gcr.io/<PROJECT_ID>/<containerName> --platform=managed --region=us-central1 --allow-unauthenticated
As it turns out I have remove public folder from .gitignore
and after that also need to tell GCF to treat public folder as static folder by creating app.yaml file in root folder
content of app.yaml
runtime: nodejs12
handlers:
- url: /static
static_dir: public
- url: /.*
script: auto
Rather than having an issue, this is more of a knowledge question. I've been diving deep on GAE's docs, Youtube videos and posts, on how to serve a full MERN stack app from a single App Engine service.
I honestly don't have a fine-grained understanding of what App Engine deployment does behind the scenes, but I understand that it exposes your service at port 8080 from a default route assigned (i.e. https://xxxxxxxx.uc.r.appspot.com).
Based on this knowledge, I thought it would be totally possible to statically serve a built React app and handle incoming queries from this same app through /graphql endpoint.
For instance:
This solves CORS since everything shares the same origin.
You limit yourself to a single App Engine service which allows you to remain on the free tier service :)
This is my project structure:
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
...
My 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.
I am just not being able to query my App Engine service back from the served to React app.
Does anyone know if what I'm doing is even possible, or there's just no way to configure App Engine with Apollo Server to serve a static webapp + expose a /graphql endpoint at the same time.
Any suggestions or ideas are extremely welcome!
--------------------------------- Update ---------------------------------
After GAEfan suggestion, I updated the app.yaml file:
Yeah okay! I think this is indeed working, I just still get a few errors on the console about resources not found so, here is the internal structure of the build/
build/
static/
css/
js/
asset-manifest.json
favicon.ico
index.html
logo192.png
manifest.json
robots.txt
service-worker.js
I already added to this suggestion json|txt|map|ico resources in the same fashion.
- url: /(.*\.(gif|png|jpg|css|js|json|txt|map|ico))$
static_files: app/build/\1
upload: app/build/.*\.(gif|png|jpg|css|js|json|txt|map|ico)$
This resolved the not found resources issue. And your wildcards already resolved the /graphql endpoint. For some reason, the WebSocket handshake is not being correctly established, but I'm not sure if that's a direct limitation from App Engine, or that the protocol is blocked by default.
Does anyone have knowledge of Websockets over App Engine?
Still more questions, but I'll add this as a partial/temporary answer...
Your first 2 url handlers in app.yaml are duplicates. URL handling with match the first one, and send everything to ...index.html. I assume you have some js, css, or other static files in the build directory. Those will never be made available to the browser. So, you need to use better regex routing, with wildcards, etc.
Let's do these one at a time:
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
Next, let's test for .js, .css, etc.:
- url: /(.*\.(gif|png|jpg|css|js))$
static_files: app/build/\1
upload: app/build/.*\.(gif|png|jpg|css|js)$
Then (assuming you have graphql working properly, you can send all other requests there:
- url: /graphql
script: auto
or even:
- url: /(.*) # catches everything else!
script: auto
Show the files or directory tree inside your /build directory, and we can make sure we've accounted for everything.
I am using express with webpack-dev-middleware and webpack-hot-middleware in my development environment. I build a storage/DFS module that works in a similar way as GitHub. You paste a URL and it opens up a folder or a file. The problem now that I have is, when I paste a URL that contains a file extension at the end as in (/storage/folder1/folder2/file.py) I get 'Cannot GET /storage/folder1/folder2/file.py'.
It is a VUE app and for routing I am using vue-router. The path configured in VUE app is:
path: 'storage/*'
Using as a template for VUE app: https://admin.vuebulma.com/#/
Any suggestions on how fix this?